Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1 | //===- Option.h - Abstract Driver Options -----------------------*- C++ -*-===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| 10 | #ifndef LLVM_OPTION_OPTION_H |
| 11 | #define LLVM_OPTION_OPTION_H |
| 12 | |
| 13 | #include "llvm/ADT/SmallVector.h" |
| 14 | #include "llvm/ADT/StringRef.h" |
| 15 | #include "llvm/Option/OptSpecifier.h" |
| 16 | #include "llvm/Option/OptTable.h" |
| 17 | #include "llvm/Support/ErrorHandling.h" |
| 18 | #include <cassert> |
| 19 | #include <string> |
| 20 | |
| 21 | namespace llvm { |
| 22 | |
| 23 | class raw_ostream; |
| 24 | |
| 25 | namespace opt { |
| 26 | |
| 27 | class Arg; |
| 28 | class ArgList; |
| 29 | |
| 30 | /// ArgStringList - Type used for constructing argv lists for subprocesses. |
| 31 | using ArgStringList = SmallVector<const char *, 16>; |
| 32 | |
| 33 | /// Base flags for all options. Custom flags may be added after. |
| 34 | enum DriverFlag { |
| 35 | HelpHidden = (1 << 0), |
| 36 | RenderAsInput = (1 << 1), |
| 37 | RenderJoined = (1 << 2), |
| 38 | RenderSeparate = (1 << 3) |
| 39 | }; |
| 40 | |
| 41 | /// Option - Abstract representation for a single form of driver |
| 42 | /// argument. |
| 43 | /// |
| 44 | /// An Option class represents a form of option that the driver |
| 45 | /// takes, for example how many arguments the option has and how |
| 46 | /// they can be provided. Individual option instances store |
| 47 | /// additional information about what group the option is a member |
| 48 | /// of (if any), if the option is an alias, and a number of |
| 49 | /// flags. At runtime the driver parses the command line into |
| 50 | /// concrete Arg instances, each of which corresponds to a |
| 51 | /// particular Option instance. |
| 52 | class Option { |
| 53 | public: |
| 54 | enum OptionClass { |
| 55 | GroupClass = 0, |
| 56 | InputClass, |
| 57 | UnknownClass, |
| 58 | FlagClass, |
| 59 | JoinedClass, |
| 60 | ValuesClass, |
| 61 | SeparateClass, |
| 62 | RemainingArgsClass, |
| 63 | RemainingArgsJoinedClass, |
| 64 | CommaJoinedClass, |
| 65 | MultiArgClass, |
| 66 | JoinedOrSeparateClass, |
| 67 | JoinedAndSeparateClass |
| 68 | }; |
| 69 | |
| 70 | enum RenderStyleKind { |
| 71 | RenderCommaJoinedStyle, |
| 72 | RenderJoinedStyle, |
| 73 | RenderSeparateStyle, |
| 74 | RenderValuesStyle |
| 75 | }; |
| 76 | |
| 77 | protected: |
| 78 | const OptTable::Info *Info; |
| 79 | const OptTable *Owner; |
| 80 | |
| 81 | public: |
| 82 | Option(const OptTable::Info *Info, const OptTable *Owner); |
| 83 | |
| 84 | bool isValid() const { |
| 85 | return Info != nullptr; |
| 86 | } |
| 87 | |
| 88 | unsigned getID() const { |
| 89 | assert(Info && "Must have a valid info!"); |
| 90 | return Info->ID; |
| 91 | } |
| 92 | |
| 93 | OptionClass getKind() const { |
| 94 | assert(Info && "Must have a valid info!"); |
| 95 | return OptionClass(Info->Kind); |
| 96 | } |
| 97 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame^] | 98 | /// Get the name of this option without any prefix. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 99 | StringRef getName() const { |
| 100 | assert(Info && "Must have a valid info!"); |
| 101 | return Info->Name; |
| 102 | } |
| 103 | |
| 104 | const Option getGroup() const { |
| 105 | assert(Info && "Must have a valid info!"); |
| 106 | assert(Owner && "Must have a valid owner!"); |
| 107 | return Owner->getOption(Info->GroupID); |
| 108 | } |
| 109 | |
| 110 | const Option getAlias() const { |
| 111 | assert(Info && "Must have a valid info!"); |
| 112 | assert(Owner && "Must have a valid owner!"); |
| 113 | return Owner->getOption(Info->AliasID); |
| 114 | } |
| 115 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame^] | 116 | /// Get the alias arguments as a \0 separated list. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 117 | /// E.g. ["foo", "bar"] would be returned as "foo\0bar\0". |
| 118 | const char *getAliasArgs() const { |
| 119 | assert(Info && "Must have a valid info!"); |
| 120 | assert((!Info->AliasArgs || Info->AliasArgs[0] != 0) && |
| 121 | "AliasArgs should be either 0 or non-empty."); |
| 122 | |
| 123 | return Info->AliasArgs; |
| 124 | } |
| 125 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame^] | 126 | /// Get the default prefix for this option. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 127 | StringRef getPrefix() const { |
| 128 | const char *Prefix = *Info->Prefixes; |
| 129 | return Prefix ? Prefix : StringRef(); |
| 130 | } |
| 131 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame^] | 132 | /// Get the name of this option with the default prefix. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 133 | std::string getPrefixedName() const { |
| 134 | std::string Ret = getPrefix(); |
| 135 | Ret += getName(); |
| 136 | return Ret; |
| 137 | } |
| 138 | |
| 139 | unsigned getNumArgs() const { return Info->Param; } |
| 140 | |
| 141 | bool hasNoOptAsInput() const { return Info->Flags & RenderAsInput;} |
| 142 | |
| 143 | RenderStyleKind getRenderStyle() const { |
| 144 | if (Info->Flags & RenderJoined) |
| 145 | return RenderJoinedStyle; |
| 146 | if (Info->Flags & RenderSeparate) |
| 147 | return RenderSeparateStyle; |
| 148 | switch (getKind()) { |
| 149 | case GroupClass: |
| 150 | case InputClass: |
| 151 | case UnknownClass: |
| 152 | return RenderValuesStyle; |
| 153 | case JoinedClass: |
| 154 | case JoinedAndSeparateClass: |
| 155 | return RenderJoinedStyle; |
| 156 | case CommaJoinedClass: |
| 157 | return RenderCommaJoinedStyle; |
| 158 | case FlagClass: |
| 159 | case ValuesClass: |
| 160 | case SeparateClass: |
| 161 | case MultiArgClass: |
| 162 | case JoinedOrSeparateClass: |
| 163 | case RemainingArgsClass: |
| 164 | case RemainingArgsJoinedClass: |
| 165 | return RenderSeparateStyle; |
| 166 | } |
| 167 | llvm_unreachable("Unexpected kind!"); |
| 168 | } |
| 169 | |
| 170 | /// Test if this option has the flag \a Val. |
| 171 | bool hasFlag(unsigned Val) const { |
| 172 | return Info->Flags & Val; |
| 173 | } |
| 174 | |
| 175 | /// getUnaliasedOption - Return the final option this option |
| 176 | /// aliases (itself, if the option has no alias). |
| 177 | const Option getUnaliasedOption() const { |
| 178 | const Option Alias = getAlias(); |
| 179 | if (Alias.isValid()) return Alias.getUnaliasedOption(); |
| 180 | return *this; |
| 181 | } |
| 182 | |
| 183 | /// getRenderName - Return the name to use when rendering this |
| 184 | /// option. |
| 185 | StringRef getRenderName() const { |
| 186 | return getUnaliasedOption().getName(); |
| 187 | } |
| 188 | |
| 189 | /// matches - Predicate for whether this option is part of the |
| 190 | /// given option (which may be a group). |
| 191 | /// |
| 192 | /// Note that matches against options which are an alias should never be |
| 193 | /// done -- aliases do not participate in matching and so such a query will |
| 194 | /// always be false. |
| 195 | bool matches(OptSpecifier ID) const; |
| 196 | |
| 197 | /// accept - Potentially accept the current argument, returning a |
| 198 | /// new Arg instance, or 0 if the option does not accept this |
| 199 | /// argument (or the argument is missing values). |
| 200 | /// |
| 201 | /// If the option accepts the current argument, accept() sets |
| 202 | /// Index to the position where argument parsing should resume |
| 203 | /// (even if the argument is missing values). |
| 204 | /// |
| 205 | /// \param ArgSize The number of bytes taken up by the matched Option prefix |
| 206 | /// and name. This is used to determine where joined values |
| 207 | /// start. |
| 208 | Arg *accept(const ArgList &Args, unsigned &Index, unsigned ArgSize) const; |
| 209 | |
| 210 | void print(raw_ostream &O) const; |
| 211 | void dump() const; |
| 212 | }; |
| 213 | |
| 214 | } // end namespace opt |
| 215 | |
| 216 | } // end namespace llvm |
| 217 | |
| 218 | #endif // LLVM_OPTION_OPTION_H |