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