| //===- Option.h - Abstract Driver Options -----------------------*- C++ -*-===// |
| // |
| // 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_OPTION_OPTION_H |
| #define LLVM_OPTION_OPTION_H |
| |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/Option/OptSpecifier.h" |
| #include "llvm/Option/OptTable.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include <cassert> |
| #include <string> |
| |
| namespace llvm { |
| |
| class raw_ostream; |
| |
| namespace opt { |
| |
| class Arg; |
| class ArgList; |
| |
| /// ArgStringList - Type used for constructing argv lists for subprocesses. |
| using ArgStringList = SmallVector<const char *, 16>; |
| |
| /// Base flags for all options. Custom flags may be added after. |
| enum DriverFlag { |
| HelpHidden = (1 << 0), |
| RenderAsInput = (1 << 1), |
| RenderJoined = (1 << 2), |
| RenderSeparate = (1 << 3) |
| }; |
| |
| /// Option - Abstract representation for a single form of driver |
| /// argument. |
| /// |
| /// An Option class represents a form of option that the driver |
| /// takes, for example how many arguments the option has and how |
| /// they can be provided. Individual option instances store |
| /// additional information about what group the option is a member |
| /// of (if any), if the option is an alias, and a number of |
| /// flags. At runtime the driver parses the command line into |
| /// concrete Arg instances, each of which corresponds to a |
| /// particular Option instance. |
| class Option { |
| public: |
| enum OptionClass { |
| GroupClass = 0, |
| InputClass, |
| UnknownClass, |
| FlagClass, |
| JoinedClass, |
| ValuesClass, |
| SeparateClass, |
| RemainingArgsClass, |
| RemainingArgsJoinedClass, |
| CommaJoinedClass, |
| MultiArgClass, |
| JoinedOrSeparateClass, |
| JoinedAndSeparateClass |
| }; |
| |
| enum RenderStyleKind { |
| RenderCommaJoinedStyle, |
| RenderJoinedStyle, |
| RenderSeparateStyle, |
| RenderValuesStyle |
| }; |
| |
| protected: |
| const OptTable::Info *Info; |
| const OptTable *Owner; |
| |
| public: |
| Option(const OptTable::Info *Info, const OptTable *Owner); |
| |
| bool isValid() const { |
| return Info != nullptr; |
| } |
| |
| unsigned getID() const { |
| assert(Info && "Must have a valid info!"); |
| return Info->ID; |
| } |
| |
| OptionClass getKind() const { |
| assert(Info && "Must have a valid info!"); |
| return OptionClass(Info->Kind); |
| } |
| |
| /// Get the name of this option without any prefix. |
| StringRef getName() const { |
| assert(Info && "Must have a valid info!"); |
| return Info->Name; |
| } |
| |
| const Option getGroup() const { |
| assert(Info && "Must have a valid info!"); |
| assert(Owner && "Must have a valid owner!"); |
| return Owner->getOption(Info->GroupID); |
| } |
| |
| const Option getAlias() const { |
| assert(Info && "Must have a valid info!"); |
| assert(Owner && "Must have a valid owner!"); |
| return Owner->getOption(Info->AliasID); |
| } |
| |
| /// Get the alias arguments as a \0 separated list. |
| /// E.g. ["foo", "bar"] would be returned as "foo\0bar\0". |
| const char *getAliasArgs() const { |
| assert(Info && "Must have a valid info!"); |
| assert((!Info->AliasArgs || Info->AliasArgs[0] != 0) && |
| "AliasArgs should be either 0 or non-empty."); |
| |
| return Info->AliasArgs; |
| } |
| |
| /// Get the default prefix for this option. |
| StringRef getPrefix() const { |
| return Info->Prefixes.empty() |
| ? StringRef() |
| : static_cast<const StringRef &>(Info->Prefixes[0]); |
| } |
| |
| /// Get the name of this option with the default prefix. |
| std::string getPrefixedName() const { |
| std::string Ret(getPrefix()); |
| Ret += getName(); |
| return Ret; |
| } |
| |
| /// Get the help text for this option. |
| StringRef getHelpText() const { |
| assert(Info && "Must have a valid info!"); |
| return Info->HelpText; |
| } |
| |
| /// Get the meta-variable list for this option. |
| StringRef getMetaVar() const { |
| assert(Info && "Must have a valid info!"); |
| return Info->MetaVar; |
| } |
| |
| unsigned getNumArgs() const { return Info->Param; } |
| |
| bool hasNoOptAsInput() const { return Info->Flags & RenderAsInput;} |
| |
| RenderStyleKind getRenderStyle() const { |
| if (Info->Flags & RenderJoined) |
| return RenderJoinedStyle; |
| if (Info->Flags & RenderSeparate) |
| return RenderSeparateStyle; |
| switch (getKind()) { |
| case GroupClass: |
| case InputClass: |
| case UnknownClass: |
| return RenderValuesStyle; |
| case JoinedClass: |
| case JoinedAndSeparateClass: |
| return RenderJoinedStyle; |
| case CommaJoinedClass: |
| return RenderCommaJoinedStyle; |
| case FlagClass: |
| case ValuesClass: |
| case SeparateClass: |
| case MultiArgClass: |
| case JoinedOrSeparateClass: |
| case RemainingArgsClass: |
| case RemainingArgsJoinedClass: |
| return RenderSeparateStyle; |
| } |
| llvm_unreachable("Unexpected kind!"); |
| } |
| |
| /// Test if this option has the flag \a Val. |
| bool hasFlag(unsigned Val) const { |
| return Info->Flags & Val; |
| } |
| |
| /// getUnaliasedOption - Return the final option this option |
| /// aliases (itself, if the option has no alias). |
| const Option getUnaliasedOption() const { |
| const Option Alias = getAlias(); |
| if (Alias.isValid()) return Alias.getUnaliasedOption(); |
| return *this; |
| } |
| |
| /// getRenderName - Return the name to use when rendering this |
| /// option. |
| StringRef getRenderName() const { |
| return getUnaliasedOption().getName(); |
| } |
| |
| /// matches - Predicate for whether this option is part of the |
| /// given option (which may be a group). |
| /// |
| /// Note that matches against options which are an alias should never be |
| /// done -- aliases do not participate in matching and so such a query will |
| /// always be false. |
| bool matches(OptSpecifier ID) const; |
| |
| /// Potentially accept the current argument, returning a new Arg instance, |
| /// or 0 if the option does not accept this argument (or the argument is |
| /// missing values). |
| /// |
| /// If the option accepts the current argument, accept() sets |
| /// Index to the position where argument parsing should resume |
| /// (even if the argument is missing values). |
| /// |
| /// \p CurArg The argument to be matched. It may be shorter than the |
| /// underlying storage to represent a Joined argument. |
| /// \p GroupedShortOption If true, we are handling the fallback case of |
| /// parsing a prefix of the current argument as a short option. |
| std::unique_ptr<Arg> accept(const ArgList &Args, StringRef CurArg, |
| bool GroupedShortOption, unsigned &Index) const; |
| |
| private: |
| std::unique_ptr<Arg> acceptInternal(const ArgList &Args, StringRef CurArg, |
| unsigned &Index) const; |
| |
| public: |
| void print(raw_ostream &O) const; |
| void dump() const; |
| }; |
| |
| } // end namespace opt |
| |
| } // end namespace llvm |
| |
| #endif // LLVM_OPTION_OPTION_H |