123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- //===- Option.cpp - Abstract Driver Options -------------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/ADT/StringRef.h"
- #include "llvm/ADT/Twine.h"
- #include "llvm/Config/llvm-config.h"
- #include "llvm/Option/Arg.h"
- #include "llvm/Option/ArgList.h"
- #include "llvm/Option/Option.h"
- #include "llvm/Option/OptTable.h"
- #include "llvm/Support/Compiler.h"
- #include "llvm/Support/Debug.h"
- #include "llvm/Support/ErrorHandling.h"
- #include "llvm/Support/raw_ostream.h"
- #include <cassert>
- #include <cstring>
- using namespace llvm;
- using namespace llvm::opt;
- Option::Option(const OptTable::Info *info, const OptTable *owner)
- : Info(info), Owner(owner) {
- // Multi-level aliases are not supported. This just simplifies option
- // tracking, it is not an inherent limitation.
- assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) &&
- "Multi-level aliases are not supported.");
- if (Info && getAliasArgs()) {
- assert(getAlias().isValid() && "Only alias options can have alias args.");
- assert(getKind() == FlagClass && "Only Flag aliases can have alias args.");
- assert(getAlias().getKind() != FlagClass &&
- "Cannot provide alias args to a flag option.");
- }
- }
- void Option::print(raw_ostream &O) const {
- O << "<";
- switch (getKind()) {
- #define P(N) case N: O << #N; break
- P(GroupClass);
- P(InputClass);
- P(UnknownClass);
- P(FlagClass);
- P(JoinedClass);
- P(ValuesClass);
- P(SeparateClass);
- P(CommaJoinedClass);
- P(MultiArgClass);
- P(JoinedOrSeparateClass);
- P(JoinedAndSeparateClass);
- P(RemainingArgsClass);
- P(RemainingArgsJoinedClass);
- #undef P
- }
- if (Info->Prefixes) {
- O << " Prefixes:[";
- for (const char *const *Pre = Info->Prefixes; *Pre != nullptr; ++Pre) {
- O << '"' << *Pre << (*(Pre + 1) == nullptr ? "\"" : "\", ");
- }
- O << ']';
- }
- O << " Name:\"" << getName() << '"';
- const Option Group = getGroup();
- if (Group.isValid()) {
- O << " Group:";
- Group.print(O);
- }
- const Option Alias = getAlias();
- if (Alias.isValid()) {
- O << " Alias:";
- Alias.print(O);
- }
- if (getKind() == MultiArgClass)
- O << " NumArgs:" << getNumArgs();
- O << ">\n";
- }
- #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
- LLVM_DUMP_METHOD void Option::dump() const { print(dbgs()); }
- #endif
- bool Option::matches(OptSpecifier Opt) const {
- // Aliases are never considered in matching, look through them.
- const Option Alias = getAlias();
- if (Alias.isValid())
- return Alias.matches(Opt);
- // Check exact match.
- if (getID() == Opt.getID())
- return true;
- const Option Group = getGroup();
- if (Group.isValid())
- return Group.matches(Opt);
- return false;
- }
- std::unique_ptr<Arg> Option::acceptInternal(const ArgList &Args,
- StringRef Spelling,
- unsigned &Index) const {
- size_t ArgSize = Spelling.size();
- switch (getKind()) {
- case FlagClass: {
- if (ArgSize != strlen(Args.getArgString(Index)))
- return nullptr;
- return std::make_unique<Arg>(*this, Spelling, Index++);
- }
- case JoinedClass: {
- const char *Value = Args.getArgString(Index) + ArgSize;
- return std::make_unique<Arg>(*this, Spelling, Index++, Value);
- }
- case CommaJoinedClass: {
- // Always matches.
- const char *Str = Args.getArgString(Index) + ArgSize;
- auto A = std::make_unique<Arg>(*this, Spelling, Index++);
- // Parse out the comma separated values.
- const char *Prev = Str;
- for (;; ++Str) {
- char c = *Str;
- if (!c || c == ',') {
- if (Prev != Str) {
- char *Value = new char[Str - Prev + 1];
- memcpy(Value, Prev, Str - Prev);
- Value[Str - Prev] = '\0';
- A->getValues().push_back(Value);
- }
- if (!c)
- break;
- Prev = Str + 1;
- }
- }
- A->setOwnsValues(true);
- return A;
- }
- case SeparateClass:
- // Matches iff this is an exact match.
- // FIXME: Avoid strlen.
- if (ArgSize != strlen(Args.getArgString(Index)))
- return nullptr;
- Index += 2;
- if (Index > Args.getNumInputArgStrings() ||
- Args.getArgString(Index - 1) == nullptr)
- return nullptr;
- return std::make_unique<Arg>(*this, Spelling, Index - 2,
- Args.getArgString(Index - 1));
- case MultiArgClass: {
- // Matches iff this is an exact match.
- // FIXME: Avoid strlen.
- if (ArgSize != strlen(Args.getArgString(Index)))
- return nullptr;
- Index += 1 + getNumArgs();
- if (Index > Args.getNumInputArgStrings())
- return nullptr;
- auto A = std::make_unique<Arg>(*this, Spelling, Index - 1 - getNumArgs(),
- Args.getArgString(Index - getNumArgs()));
- for (unsigned i = 1; i != getNumArgs(); ++i)
- A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
- return A;
- }
- case JoinedOrSeparateClass: {
- // If this is not an exact match, it is a joined arg.
- // FIXME: Avoid strlen.
- if (ArgSize != strlen(Args.getArgString(Index))) {
- const char *Value = Args.getArgString(Index) + ArgSize;
- return std::make_unique<Arg>(*this, Spelling, Index++, Value);
- }
- // Otherwise it must be separate.
- Index += 2;
- if (Index > Args.getNumInputArgStrings() ||
- Args.getArgString(Index - 1) == nullptr)
- return nullptr;
- return std::make_unique<Arg>(*this, Spelling, Index - 2,
- Args.getArgString(Index - 1));
- }
- case JoinedAndSeparateClass:
- // Always matches.
- Index += 2;
- if (Index > Args.getNumInputArgStrings() ||
- Args.getArgString(Index - 1) == nullptr)
- return nullptr;
- return std::make_unique<Arg>(*this, Spelling, Index - 2,
- Args.getArgString(Index - 2) + ArgSize,
- Args.getArgString(Index - 1));
- case RemainingArgsClass: {
- // Matches iff this is an exact match.
- // FIXME: Avoid strlen.
- if (ArgSize != strlen(Args.getArgString(Index)))
- return nullptr;
- auto A = std::make_unique<Arg>(*this, Spelling, Index++);
- while (Index < Args.getNumInputArgStrings() &&
- Args.getArgString(Index) != nullptr)
- A->getValues().push_back(Args.getArgString(Index++));
- return A;
- }
- case RemainingArgsJoinedClass: {
- auto A = std::make_unique<Arg>(*this, Spelling, Index);
- if (ArgSize != strlen(Args.getArgString(Index))) {
- // An inexact match means there is a joined arg.
- A->getValues().push_back(Args.getArgString(Index) + ArgSize);
- }
- Index++;
- while (Index < Args.getNumInputArgStrings() &&
- Args.getArgString(Index) != nullptr)
- A->getValues().push_back(Args.getArgString(Index++));
- return A;
- }
- default:
- llvm_unreachable("Invalid option kind!");
- }
- }
- std::unique_ptr<Arg> Option::accept(const ArgList &Args, StringRef CurArg,
- bool GroupedShortOption,
- unsigned &Index) const {
- auto A(GroupedShortOption && getKind() == FlagClass
- ? std::make_unique<Arg>(*this, CurArg, Index)
- : acceptInternal(Args, CurArg, Index));
- if (!A)
- return nullptr;
- const Option &UnaliasedOption = getUnaliasedOption();
- if (getID() == UnaliasedOption.getID())
- return A;
- // "A" is an alias for a different flag. For most clients it's more convenient
- // if this function returns unaliased Args, so create an unaliased arg for
- // returning.
- // This creates a completely new Arg object for the unaliased Arg because
- // the alias and the unaliased arg can have different Kinds and different
- // Values (due to AliasArgs<>).
- // Get the spelling from the unaliased option.
- StringRef UnaliasedSpelling = Args.MakeArgString(
- Twine(UnaliasedOption.getPrefix()) + Twine(UnaliasedOption.getName()));
- // It's a bit weird that aliased and unaliased arg share one index, but
- // the index is mostly use as a memory optimization in render().
- // Due to this, ArgList::getArgString(A->getIndex()) will return the spelling
- // of the aliased arg always, while A->getSpelling() returns either the
- // unaliased or the aliased arg, depending on which Arg object it's called on.
- auto UnaliasedA =
- std::make_unique<Arg>(UnaliasedOption, UnaliasedSpelling, A->getIndex());
- Arg *RawA = A.get();
- UnaliasedA->setAlias(std::move(A));
- if (getKind() != FlagClass) {
- // Values are usually owned by the ArgList. The exception are
- // CommaJoined flags, where the Arg owns the values. For aliased flags,
- // make the unaliased Arg the owner of the values.
- // FIXME: There aren't many uses of CommaJoined -- try removing
- // CommaJoined in favor of just calling StringRef::split(',') instead.
- UnaliasedA->getValues() = RawA->getValues();
- UnaliasedA->setOwnsValues(RawA->getOwnsValues());
- RawA->setOwnsValues(false);
- return UnaliasedA;
- }
- // FlagClass aliases can have AliasArgs<>; add those to the unaliased arg.
- if (const char *Val = getAliasArgs()) {
- while (*Val != '\0') {
- UnaliasedA->getValues().push_back(Val);
- // Move past the '\0' to the next argument.
- Val += strlen(Val) + 1;
- }
- }
- if (UnaliasedOption.getKind() == JoinedClass && !getAliasArgs())
- // A Flag alias for a Joined option must provide an argument.
- UnaliasedA->getValues().push_back("");
- return UnaliasedA;
- }
|