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 assert(Owner && "Must have a valid owner!"); 104 return Owner->getOptionName(Info->ID); 105 } 106 107 const Option getGroup() const { 108 assert(Info && "Must have a valid info!"); 109 assert(Owner && "Must have a valid owner!"); 110 return Owner->getOption(Info->GroupID); 111 } 112 113 const Option getAlias() const { 114 assert(Info && "Must have a valid info!"); 115 assert(Owner && "Must have a valid owner!"); 116 return Owner->getOption(Info->AliasID); 117 } 118 119 /// Get the alias arguments as a \0 separated list. 120 /// E.g. ["foo", "bar"] would be returned as "foo\0bar\0". 121 const char *getAliasArgs() const { 122 assert(Info && "Must have a valid info!"); 123 assert((!Info->AliasArgs || Info->AliasArgs[0] != 0) && 124 "AliasArgs should be either 0 or non-empty."); 125 126 return Info->AliasArgs; 127 } 128 129 /// Get the default prefix for this option. 130 StringRef getPrefix() const { 131 assert(Info && "Must have a valid info!"); 132 assert(Owner && "Must have a valid owner!"); 133 return Owner->getOptionPrefix(Info->ID); 134 } 135 136 /// Get the name of this option with the default prefix. 137 StringRef getPrefixedName() const { 138 assert(Info && "Must have a valid info!"); 139 assert(Owner && "Must have a valid owner!"); 140 return Owner->getOptionPrefixedName(Info->ID); 141 } 142 143 /// Get the help text for this option. 144 StringRef getHelpText() const { 145 assert(Info && "Must have a valid info!"); 146 return Info->HelpText; 147 } 148 149 /// Get the meta-variable list for this option. 150 StringRef getMetaVar() const { 151 assert(Info && "Must have a valid info!"); 152 return Info->MetaVar; 153 } 154 155 unsigned getNumArgs() const { return Info->Param; } 156 157 bool hasNoOptAsInput() const { return Info->Flags & RenderAsInput;} 158 159 RenderStyleKind getRenderStyle() const { 160 if (Info->Flags & RenderJoined) 161 return RenderJoinedStyle; 162 if (Info->Flags & RenderSeparate) 163 return RenderSeparateStyle; 164 switch (getKind()) { 165 case GroupClass: 166 case InputClass: 167 case UnknownClass: 168 return RenderValuesStyle; 169 case JoinedClass: 170 case JoinedAndSeparateClass: 171 return RenderJoinedStyle; 172 case CommaJoinedClass: 173 return RenderCommaJoinedStyle; 174 case FlagClass: 175 case ValuesClass: 176 case SeparateClass: 177 case MultiArgClass: 178 case JoinedOrSeparateClass: 179 case RemainingArgsClass: 180 case RemainingArgsJoinedClass: 181 return RenderSeparateStyle; 182 } 183 llvm_unreachable("Unexpected kind!"); 184 } 185 186 /// Test if this option has the flag \a Val. 187 bool hasFlag(unsigned Val) const { 188 return Info->Flags & Val; 189 } 190 191 /// Test if this option has the visibility flag \a Val. 192 bool hasVisibilityFlag(unsigned Val) const { 193 return Info->Visibility & Val; 194 } 195 196 /// getUnaliasedOption - Return the final option this option 197 /// aliases (itself, if the option has no alias). 198 const Option getUnaliasedOption() const { 199 const Option Alias = getAlias(); 200 if (Alias.isValid()) return Alias.getUnaliasedOption(); 201 return *this; 202 } 203 204 /// getRenderName - Return the name to use when rendering this 205 /// option. 206 StringRef getRenderName() const { 207 return getUnaliasedOption().getName(); 208 } 209 210 /// matches - Predicate for whether this option is part of the 211 /// given option (which may be a group). 212 /// 213 /// Note that matches against options which are an alias should never be 214 /// done -- aliases do not participate in matching and so such a query will 215 /// always be false. 216 bool matches(OptSpecifier ID) const; 217 218 /// Potentially accept the current argument, returning a new Arg instance, 219 /// or 0 if the option does not accept this argument (or the argument is 220 /// missing values). 221 /// 222 /// If the option accepts the current argument, accept() sets 223 /// Index to the position where argument parsing should resume 224 /// (even if the argument is missing values). 225 /// 226 /// \p CurArg The argument to be matched. It may be shorter than the 227 /// underlying storage to represent a Joined argument. 228 /// \p GroupedShortOption If true, we are handling the fallback case of 229 /// parsing a prefix of the current argument as a short option. 230 std::unique_ptr<Arg> accept(const ArgList &Args, StringRef CurArg, 231 bool GroupedShortOption, unsigned &Index) const; 232 233 private: 234 std::unique_ptr<Arg> acceptInternal(const ArgList &Args, StringRef CurArg, 235 unsigned &Index) const; 236 237 public: 238 void print(raw_ostream &O, bool AddNewLine = true) const; 239 void dump() const; 240 }; 241 242 } // end namespace opt 243 244 } // end namespace llvm 245 246 #endif // LLVM_OPTION_OPTION_H 247