LLVM API Documentation

Option.cpp
Go to the documentation of this file.
00001 //===--- Option.cpp - Abstract Driver Options -----------------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "llvm/Option/Option.h"
00011 #include "llvm/ADT/Twine.h"
00012 #include "llvm/Option/Arg.h"
00013 #include "llvm/Option/ArgList.h"
00014 #include "llvm/Support/ErrorHandling.h"
00015 #include "llvm/Support/raw_ostream.h"
00016 #include <algorithm>
00017 #include <cassert>
00018 
00019 using namespace llvm;
00020 using namespace llvm::opt;
00021 
00022 Option::Option(const OptTable::Info *info, const OptTable *owner)
00023   : Info(info), Owner(owner) {
00024 
00025   // Multi-level aliases are not supported. This just simplifies option
00026   // tracking, it is not an inherent limitation.
00027   assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) &&
00028          "Multi-level aliases are not supported.");
00029 
00030   if (Info && getAliasArgs()) {
00031     assert(getAlias().isValid() && "Only alias options can have alias args.");
00032     assert(getKind() == FlagClass && "Only Flag aliases can have alias args.");
00033     assert(getAlias().getKind() != FlagClass &&
00034            "Cannot provide alias args to a flag option.");
00035   }
00036 }
00037 
00038 Option::~Option() {
00039 }
00040 
00041 void Option::dump() const {
00042   llvm::errs() << "<";
00043   switch (getKind()) {
00044 #define P(N) case N: llvm::errs() << #N; break
00045     P(GroupClass);
00046     P(InputClass);
00047     P(UnknownClass);
00048     P(FlagClass);
00049     P(JoinedClass);
00050     P(SeparateClass);
00051     P(CommaJoinedClass);
00052     P(MultiArgClass);
00053     P(JoinedOrSeparateClass);
00054     P(JoinedAndSeparateClass);
00055     P(RemainingArgsClass);
00056 #undef P
00057   }
00058 
00059   if (Info->Prefixes) {
00060     llvm::errs() << " Prefixes:[";
00061     for (const char * const *Pre = Info->Prefixes; *Pre != nullptr; ++Pre) {
00062       llvm::errs() << '"' << *Pre << (*(Pre + 1) == nullptr ? "\"" : "\", ");
00063     }
00064     llvm::errs() << ']';
00065   }
00066 
00067   llvm::errs() << " Name:\"" << getName() << '"';
00068 
00069   const Option Group = getGroup();
00070   if (Group.isValid()) {
00071     llvm::errs() << " Group:";
00072     Group.dump();
00073   }
00074 
00075   const Option Alias = getAlias();
00076   if (Alias.isValid()) {
00077     llvm::errs() << " Alias:";
00078     Alias.dump();
00079   }
00080 
00081   if (getKind() == MultiArgClass)
00082     llvm::errs() << " NumArgs:" << getNumArgs();
00083 
00084   llvm::errs() << ">\n";
00085 }
00086 
00087 bool Option::matches(OptSpecifier Opt) const {
00088   // Aliases are never considered in matching, look through them.
00089   const Option Alias = getAlias();
00090   if (Alias.isValid())
00091     return Alias.matches(Opt);
00092 
00093   // Check exact match.
00094   if (getID() == Opt.getID())
00095     return true;
00096 
00097   const Option Group = getGroup();
00098   if (Group.isValid())
00099     return Group.matches(Opt);
00100   return false;
00101 }
00102 
00103 Arg *Option::accept(const ArgList &Args,
00104                     unsigned &Index,
00105                     unsigned ArgSize) const {
00106   const Option &UnaliasedOption = getUnaliasedOption();
00107   StringRef Spelling;
00108   // If the option was an alias, get the spelling from the unaliased one.
00109   if (getID() == UnaliasedOption.getID()) {
00110     Spelling = StringRef(Args.getArgString(Index), ArgSize);
00111   } else {
00112     Spelling = Args.MakeArgString(Twine(UnaliasedOption.getPrefix()) +
00113                                   Twine(UnaliasedOption.getName()));
00114   }
00115 
00116   switch (getKind()) {
00117   case FlagClass: {
00118     if (ArgSize != strlen(Args.getArgString(Index)))
00119       return nullptr;
00120 
00121     Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
00122     if (getAliasArgs()) {
00123       const char *Val = getAliasArgs();
00124       while (*Val != '\0') {
00125         A->getValues().push_back(Val);
00126 
00127         // Move past the '\0' to the next argument.
00128         Val += strlen(Val) + 1;
00129       }
00130     }
00131     return A;
00132   }
00133   case JoinedClass: {
00134     const char *Value = Args.getArgString(Index) + ArgSize;
00135     return new Arg(UnaliasedOption, Spelling, Index++, Value);
00136   }
00137   case CommaJoinedClass: {
00138     // Always matches.
00139     const char *Str = Args.getArgString(Index) + ArgSize;
00140     Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
00141 
00142     // Parse out the comma separated values.
00143     const char *Prev = Str;
00144     for (;; ++Str) {
00145       char c = *Str;
00146 
00147       if (!c || c == ',') {
00148         if (Prev != Str) {
00149           char *Value = new char[Str - Prev + 1];
00150           memcpy(Value, Prev, Str - Prev);
00151           Value[Str - Prev] = '\0';
00152           A->getValues().push_back(Value);
00153         }
00154 
00155         if (!c)
00156           break;
00157 
00158         Prev = Str + 1;
00159       }
00160     }
00161     A->setOwnsValues(true);
00162 
00163     return A;
00164   }
00165   case SeparateClass:
00166     // Matches iff this is an exact match.
00167     // FIXME: Avoid strlen.
00168     if (ArgSize != strlen(Args.getArgString(Index)))
00169       return nullptr;
00170 
00171     Index += 2;
00172     if (Index > Args.getNumInputArgStrings() ||
00173         Args.getArgString(Index - 1) == nullptr)
00174       return nullptr;
00175 
00176     return new Arg(UnaliasedOption, Spelling,
00177                    Index - 2, Args.getArgString(Index - 1));
00178   case MultiArgClass: {
00179     // Matches iff this is an exact match.
00180     // FIXME: Avoid strlen.
00181     if (ArgSize != strlen(Args.getArgString(Index)))
00182       return nullptr;
00183 
00184     Index += 1 + getNumArgs();
00185     if (Index > Args.getNumInputArgStrings())
00186       return nullptr;
00187 
00188     Arg *A = new Arg(UnaliasedOption, Spelling, Index - 1 - getNumArgs(),
00189                       Args.getArgString(Index - getNumArgs()));
00190     for (unsigned i = 1; i != getNumArgs(); ++i)
00191       A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
00192     return A;
00193   }
00194   case JoinedOrSeparateClass: {
00195     // If this is not an exact match, it is a joined arg.
00196     // FIXME: Avoid strlen.
00197     if (ArgSize != strlen(Args.getArgString(Index))) {
00198       const char *Value = Args.getArgString(Index) + ArgSize;
00199       return new Arg(*this, Spelling, Index++, Value);
00200     }
00201 
00202     // Otherwise it must be separate.
00203     Index += 2;
00204     if (Index > Args.getNumInputArgStrings() ||
00205         Args.getArgString(Index - 1) == nullptr)
00206       return nullptr;
00207 
00208     return new Arg(UnaliasedOption, Spelling,
00209                    Index - 2, Args.getArgString(Index - 1));
00210   }
00211   case JoinedAndSeparateClass:
00212     // Always matches.
00213     Index += 2;
00214     if (Index > Args.getNumInputArgStrings() ||
00215         Args.getArgString(Index - 1) == nullptr)
00216       return nullptr;
00217 
00218     return new Arg(UnaliasedOption, Spelling, Index - 2,
00219                    Args.getArgString(Index - 2) + ArgSize,
00220                    Args.getArgString(Index - 1));
00221   case RemainingArgsClass: {
00222     // Matches iff this is an exact match.
00223     // FIXME: Avoid strlen.
00224     if (ArgSize != strlen(Args.getArgString(Index)))
00225       return nullptr;
00226     Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
00227     while (Index < Args.getNumInputArgStrings() &&
00228            Args.getArgString(Index) != nullptr)
00229       A->getValues().push_back(Args.getArgString(Index++));
00230     return A;
00231   }
00232   default:
00233     llvm_unreachable("Invalid option kind!");
00234   }
00235 }