| 1 | //===- Option.cpp - Abstract Driver Options -------------------------------===// |
| 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 | #include "llvm/Option/Option.h" |
| 10 | #include "llvm/ADT/StringRef.h" |
| 11 | #include "llvm/ADT/Twine.h" |
| 12 | #include "llvm/Config/llvm-config.h" |
| 13 | #include "llvm/Option/Arg.h" |
| 14 | #include "llvm/Option/ArgList.h" |
| 15 | #include "llvm/Option/OptTable.h" |
| 16 | #include "llvm/Support/Compiler.h" |
| 17 | #include "llvm/Support/Debug.h" |
| 18 | #include "llvm/Support/ErrorHandling.h" |
| 19 | #include "llvm/Support/raw_ostream.h" |
| 20 | #include <cassert> |
| 21 | |
| 22 | using namespace llvm; |
| 23 | using namespace llvm::opt; |
| 24 | |
| 25 | Option::Option(const OptTable::Info *info, const OptTable *owner) |
| 26 | : Info(info), Owner(owner) { |
| 27 | // Multi-level aliases are not supported. This just simplifies option |
| 28 | // tracking, it is not an inherent limitation. |
| 29 | assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) && |
| 30 | "Multi-level aliases are not supported." ); |
| 31 | |
| 32 | if (Info && getAliasArgs()) { |
| 33 | assert(getAlias().isValid() && "Only alias options can have alias args." ); |
| 34 | assert(getKind() == FlagClass && "Only Flag aliases can have alias args." ); |
| 35 | assert(getAlias().getKind() != FlagClass && |
| 36 | "Cannot provide alias args to a flag option." ); |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | void Option::print(raw_ostream &O, bool AddNewLine) const { |
| 41 | O << "<" ; |
| 42 | switch (getKind()) { |
| 43 | #define P(N) case N: O << #N; break |
| 44 | P(GroupClass); |
| 45 | P(InputClass); |
| 46 | P(UnknownClass); |
| 47 | P(FlagClass); |
| 48 | P(JoinedClass); |
| 49 | P(ValuesClass); |
| 50 | P(SeparateClass); |
| 51 | P(CommaJoinedClass); |
| 52 | P(MultiArgClass); |
| 53 | P(JoinedOrSeparateClass); |
| 54 | P(JoinedAndSeparateClass); |
| 55 | P(RemainingArgsClass); |
| 56 | P(RemainingArgsJoinedClass); |
| 57 | #undef P |
| 58 | } |
| 59 | |
| 60 | if (!Info->hasNoPrefix()) { |
| 61 | O << " Prefixes:[" ; |
| 62 | for (size_t I = 0, N = Info->getNumPrefixes(PrefixesTable: Owner->getPrefixesTable()); |
| 63 | I != N; ++I) |
| 64 | O << '"' |
| 65 | << Info->getPrefix(StrTable: Owner->getStrTable(), PrefixesTable: Owner->getPrefixesTable(), PrefixIndex: I) |
| 66 | << (I == N - 1 ? "\"" : "\", " ); |
| 67 | O << ']'; |
| 68 | } |
| 69 | |
| 70 | O << " Name:\"" << getName() << '"'; |
| 71 | |
| 72 | const Option Group = getGroup(); |
| 73 | if (Group.isValid()) { |
| 74 | O << " Group:" ; |
| 75 | Group.print(O, /*AddNewLine=*/false); |
| 76 | } |
| 77 | |
| 78 | const Option Alias = getAlias(); |
| 79 | if (Alias.isValid()) { |
| 80 | O << " Alias:" ; |
| 81 | Alias.print(O, /*AddNewLine=*/false); |
| 82 | } |
| 83 | |
| 84 | if (getKind() == MultiArgClass) |
| 85 | O << " NumArgs:" << getNumArgs(); |
| 86 | |
| 87 | O << ">" ; |
| 88 | if (AddNewLine) |
| 89 | O << "\n" ; |
| 90 | } |
| 91 | |
| 92 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
| 93 | LLVM_DUMP_METHOD void Option::dump() const { print(dbgs()); } |
| 94 | #endif |
| 95 | |
| 96 | bool Option::matches(OptSpecifier Opt) const { |
| 97 | // Aliases are never considered in matching, look through them. |
| 98 | const Option Alias = getAlias(); |
| 99 | if (Alias.isValid()) |
| 100 | return Alias.matches(Opt); |
| 101 | |
| 102 | // Check exact match. |
| 103 | if (getID() == Opt.getID()) |
| 104 | return true; |
| 105 | |
| 106 | const Option Group = getGroup(); |
| 107 | if (Group.isValid()) |
| 108 | return Group.matches(Opt); |
| 109 | return false; |
| 110 | } |
| 111 | |
| 112 | std::unique_ptr<Arg> Option::acceptInternal(const ArgList &Args, |
| 113 | StringRef Spelling, |
| 114 | unsigned &Index) const { |
| 115 | const size_t SpellingSize = Spelling.size(); |
| 116 | const size_t ArgStringSize = StringRef(Args.getArgString(Index)).size(); |
| 117 | switch (getKind()) { |
| 118 | case FlagClass: { |
| 119 | if (SpellingSize != ArgStringSize) |
| 120 | return nullptr; |
| 121 | return std::make_unique<Arg>(args: *this, args&: Spelling, args: Index++); |
| 122 | } |
| 123 | case JoinedClass: { |
| 124 | const char *Value = Args.getArgString(Index) + SpellingSize; |
| 125 | return std::make_unique<Arg>(args: *this, args&: Spelling, args: Index++, args&: Value); |
| 126 | } |
| 127 | case CommaJoinedClass: { |
| 128 | // Always matches. |
| 129 | const char *Str = Args.getArgString(Index) + SpellingSize; |
| 130 | auto A = std::make_unique<Arg>(args: *this, args&: Spelling, args: Index++); |
| 131 | |
| 132 | // Parse out the comma separated values. |
| 133 | const char *Prev = Str; |
| 134 | for (;; ++Str) { |
| 135 | char c = *Str; |
| 136 | |
| 137 | if (!c || c == ',') { |
| 138 | if (Prev != Str) { |
| 139 | char *Value = new char[Str - Prev + 1]; |
| 140 | memcpy(dest: Value, src: Prev, n: Str - Prev); |
| 141 | Value[Str - Prev] = '\0'; |
| 142 | A->getValues().push_back(Elt: Value); |
| 143 | } |
| 144 | |
| 145 | if (!c) |
| 146 | break; |
| 147 | |
| 148 | Prev = Str + 1; |
| 149 | } |
| 150 | } |
| 151 | A->setOwnsValues(true); |
| 152 | |
| 153 | return A; |
| 154 | } |
| 155 | case SeparateClass: |
| 156 | // Matches iff this is an exact match. |
| 157 | if (SpellingSize != ArgStringSize) |
| 158 | return nullptr; |
| 159 | |
| 160 | Index += 2; |
| 161 | if (Index > Args.getNumInputArgStrings() || |
| 162 | Args.getArgString(Index: Index - 1) == nullptr) |
| 163 | return nullptr; |
| 164 | |
| 165 | return std::make_unique<Arg>(args: *this, args&: Spelling, args: Index - 2, |
| 166 | args: Args.getArgString(Index: Index - 1)); |
| 167 | case MultiArgClass: { |
| 168 | // Matches iff this is an exact match. |
| 169 | if (SpellingSize != ArgStringSize) |
| 170 | return nullptr; |
| 171 | |
| 172 | Index += 1 + getNumArgs(); |
| 173 | if (Index > Args.getNumInputArgStrings()) |
| 174 | return nullptr; |
| 175 | |
| 176 | auto A = std::make_unique<Arg>(args: *this, args&: Spelling, args: Index - 1 - getNumArgs(), |
| 177 | args: Args.getArgString(Index: Index - getNumArgs())); |
| 178 | for (unsigned i = 1; i != getNumArgs(); ++i) |
| 179 | A->getValues().push_back(Elt: Args.getArgString(Index: Index - getNumArgs() + i)); |
| 180 | return A; |
| 181 | } |
| 182 | case JoinedOrSeparateClass: { |
| 183 | // If this is not an exact match, it is a joined arg. |
| 184 | if (SpellingSize != ArgStringSize) { |
| 185 | const char *Value = Args.getArgString(Index) + SpellingSize; |
| 186 | return std::make_unique<Arg>(args: *this, args&: Spelling, args: Index++, args&: Value); |
| 187 | } |
| 188 | |
| 189 | // Otherwise it must be separate. |
| 190 | Index += 2; |
| 191 | if (Index > Args.getNumInputArgStrings() || |
| 192 | Args.getArgString(Index: Index - 1) == nullptr) |
| 193 | return nullptr; |
| 194 | |
| 195 | return std::make_unique<Arg>(args: *this, args&: Spelling, args: Index - 2, |
| 196 | args: Args.getArgString(Index: Index - 1)); |
| 197 | } |
| 198 | case JoinedAndSeparateClass: |
| 199 | // Always matches. |
| 200 | Index += 2; |
| 201 | if (Index > Args.getNumInputArgStrings() || |
| 202 | Args.getArgString(Index: Index - 1) == nullptr) |
| 203 | return nullptr; |
| 204 | |
| 205 | return std::make_unique<Arg>(args: *this, args&: Spelling, args: Index - 2, |
| 206 | args: Args.getArgString(Index: Index - 2) + SpellingSize, |
| 207 | args: Args.getArgString(Index: Index - 1)); |
| 208 | case RemainingArgsClass: { |
| 209 | // Matches iff this is an exact match. |
| 210 | if (SpellingSize != ArgStringSize) |
| 211 | return nullptr; |
| 212 | auto A = std::make_unique<Arg>(args: *this, args&: Spelling, args: Index++); |
| 213 | while (Index < Args.getNumInputArgStrings() && |
| 214 | Args.getArgString(Index) != nullptr) |
| 215 | A->getValues().push_back(Elt: Args.getArgString(Index: Index++)); |
| 216 | return A; |
| 217 | } |
| 218 | case RemainingArgsJoinedClass: { |
| 219 | auto A = std::make_unique<Arg>(args: *this, args&: Spelling, args&: Index); |
| 220 | if (SpellingSize != ArgStringSize) { |
| 221 | // An inexact match means there is a joined arg. |
| 222 | A->getValues().push_back(Elt: Args.getArgString(Index) + SpellingSize); |
| 223 | } |
| 224 | Index++; |
| 225 | while (Index < Args.getNumInputArgStrings() && |
| 226 | Args.getArgString(Index) != nullptr) |
| 227 | A->getValues().push_back(Elt: Args.getArgString(Index: Index++)); |
| 228 | return A; |
| 229 | } |
| 230 | |
| 231 | default: |
| 232 | llvm_unreachable("Invalid option kind!" ); |
| 233 | } |
| 234 | } |
| 235 | |
| 236 | std::unique_ptr<Arg> Option::accept(const ArgList &Args, StringRef CurArg, |
| 237 | bool GroupedShortOption, |
| 238 | unsigned &Index) const { |
| 239 | auto A(GroupedShortOption && getKind() == FlagClass |
| 240 | ? std::make_unique<Arg>(args: *this, args&: CurArg, args&: Index) |
| 241 | : acceptInternal(Args, Spelling: CurArg, Index)); |
| 242 | if (!A) |
| 243 | return nullptr; |
| 244 | |
| 245 | const Option &UnaliasedOption = getUnaliasedOption(); |
| 246 | if (getID() == UnaliasedOption.getID()) |
| 247 | return A; |
| 248 | |
| 249 | // "A" is an alias for a different flag. For most clients it's more convenient |
| 250 | // if this function returns unaliased Args, so create an unaliased arg for |
| 251 | // returning. |
| 252 | |
| 253 | // This creates a completely new Arg object for the unaliased Arg because |
| 254 | // the alias and the unaliased arg can have different Kinds and different |
| 255 | // Values (due to AliasArgs<>). |
| 256 | |
| 257 | // Get the spelling from the unaliased option. |
| 258 | StringRef UnaliasedSpelling = Args.MakeArgString( |
| 259 | Str: Twine(UnaliasedOption.getPrefix()) + Twine(UnaliasedOption.getName())); |
| 260 | |
| 261 | // It's a bit weird that aliased and unaliased arg share one index, but |
| 262 | // the index is mostly use as a memory optimization in render(). |
| 263 | // Due to this, ArgList::getArgString(A->getIndex()) will return the spelling |
| 264 | // of the aliased arg always, while A->getSpelling() returns either the |
| 265 | // unaliased or the aliased arg, depending on which Arg object it's called on. |
| 266 | auto UnaliasedA = |
| 267 | std::make_unique<Arg>(args: UnaliasedOption, args&: UnaliasedSpelling, args: A->getIndex()); |
| 268 | Arg *RawA = A.get(); |
| 269 | UnaliasedA->setAlias(std::move(A)); |
| 270 | |
| 271 | if (getKind() != FlagClass) { |
| 272 | // Values are usually owned by the ArgList. The exception are |
| 273 | // CommaJoined flags, where the Arg owns the values. For aliased flags, |
| 274 | // make the unaliased Arg the owner of the values. |
| 275 | // FIXME: There aren't many uses of CommaJoined -- try removing |
| 276 | // CommaJoined in favor of just calling StringRef::split(',') instead. |
| 277 | UnaliasedA->getValues() = RawA->getValues(); |
| 278 | UnaliasedA->setOwnsValues(RawA->getOwnsValues()); |
| 279 | RawA->setOwnsValues(false); |
| 280 | return UnaliasedA; |
| 281 | } |
| 282 | |
| 283 | // FlagClass aliases can have AliasArgs<>; add those to the unaliased arg. |
| 284 | if (const char *Val = getAliasArgs()) { |
| 285 | while (*Val != '\0') { |
| 286 | UnaliasedA->getValues().push_back(Elt: Val); |
| 287 | |
| 288 | // Move past the '\0' to the next argument. |
| 289 | Val += strlen(s: Val) + 1; |
| 290 | } |
| 291 | } |
| 292 | if (UnaliasedOption.getKind() == JoinedClass && !getAliasArgs()) |
| 293 | // A Flag alias for a Joined option must provide an argument. |
| 294 | UnaliasedA->getValues().push_back(Elt: "" ); |
| 295 | return UnaliasedA; |
| 296 | } |
| 297 | |