Home | History | Annotate | Download | only in Option
      1 //===--- Option.cpp - Abstract Driver Options -----------------------------===//
      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 #include "llvm/Option/Option.h"
     11 #include "llvm/ADT/Twine.h"
     12 #include "llvm/Option/Arg.h"
     13 #include "llvm/Option/ArgList.h"
     14 #include "llvm/Support/ErrorHandling.h"
     15 #include "llvm/Support/raw_ostream.h"
     16 #include <algorithm>
     17 #include <cassert>
     18 
     19 using namespace llvm;
     20 using namespace llvm::opt;
     21 
     22 Option::Option(const OptTable::Info *info, const OptTable *owner)
     23   : Info(info), Owner(owner) {
     24 
     25   // Multi-level aliases are not supported, and alias options cannot
     26   // have groups. This just simplifies option tracking, it is not an
     27   // inherent limitation.
     28   assert((!Info || !getAlias().isValid() || (!getAlias().getAlias().isValid() &&
     29          !getGroup().isValid())) &&
     30          "Multi-level aliases and aliases with groups are unsupported.");
     31 }
     32 
     33 Option::~Option() {
     34 }
     35 
     36 void Option::dump() const {
     37   llvm::errs() << "<";
     38   switch (getKind()) {
     39 #define P(N) case N: llvm::errs() << #N; break
     40     P(GroupClass);
     41     P(InputClass);
     42     P(UnknownClass);
     43     P(FlagClass);
     44     P(JoinedClass);
     45     P(SeparateClass);
     46     P(CommaJoinedClass);
     47     P(MultiArgClass);
     48     P(JoinedOrSeparateClass);
     49     P(JoinedAndSeparateClass);
     50 #undef P
     51   }
     52 
     53   llvm::errs() << " Prefixes:[";
     54   for (const char * const *Pre = Info->Prefixes; *Pre != 0; ++Pre) {
     55     llvm::errs() << '"' << *Pre << (*(Pre + 1) == 0 ? "\"" : "\", ");
     56   }
     57   llvm::errs() << ']';
     58 
     59   llvm::errs() << " Name:\"" << getName() << '"';
     60 
     61   const Option Group = getGroup();
     62   if (Group.isValid()) {
     63     llvm::errs() << " Group:";
     64     Group.dump();
     65   }
     66 
     67   const Option Alias = getAlias();
     68   if (Alias.isValid()) {
     69     llvm::errs() << " Alias:";
     70     Alias.dump();
     71   }
     72 
     73   if (getKind() == MultiArgClass)
     74     llvm::errs() << " NumArgs:" << getNumArgs();
     75 
     76   llvm::errs() << ">\n";
     77 }
     78 
     79 bool Option::matches(OptSpecifier Opt) const {
     80   // Aliases are never considered in matching, look through them.
     81   const Option Alias = getAlias();
     82   if (Alias.isValid())
     83     return Alias.matches(Opt);
     84 
     85   // Check exact match.
     86   if (getID() == Opt.getID())
     87     return true;
     88 
     89   const Option Group = getGroup();
     90   if (Group.isValid())
     91     return Group.matches(Opt);
     92   return false;
     93 }
     94 
     95 Arg *Option::accept(const ArgList &Args,
     96                     unsigned &Index,
     97                     unsigned ArgSize) const {
     98   const Option &UnaliasedOption = getUnaliasedOption();
     99   StringRef Spelling;
    100   // If the option was an alias, get the spelling from the unaliased one.
    101   if (getID() == UnaliasedOption.getID()) {
    102     Spelling = StringRef(Args.getArgString(Index), ArgSize);
    103   } else {
    104     Spelling = Args.MakeArgString(Twine(UnaliasedOption.getPrefix()) +
    105                                   Twine(UnaliasedOption.getName()));
    106   }
    107 
    108   switch (getKind()) {
    109   case FlagClass:
    110     if (ArgSize != strlen(Args.getArgString(Index)))
    111       return 0;
    112 
    113     return new Arg(UnaliasedOption, Spelling, Index++);
    114   case JoinedClass: {
    115     const char *Value = Args.getArgString(Index) + ArgSize;
    116     return new Arg(UnaliasedOption, Spelling, Index++, Value);
    117   }
    118   case CommaJoinedClass: {
    119     // Always matches.
    120     const char *Str = Args.getArgString(Index) + ArgSize;
    121     Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
    122 
    123     // Parse out the comma separated values.
    124     const char *Prev = Str;
    125     for (;; ++Str) {
    126       char c = *Str;
    127 
    128       if (!c || c == ',') {
    129         if (Prev != Str) {
    130           char *Value = new char[Str - Prev + 1];
    131           memcpy(Value, Prev, Str - Prev);
    132           Value[Str - Prev] = '\0';
    133           A->getValues().push_back(Value);
    134         }
    135 
    136         if (!c)
    137           break;
    138 
    139         Prev = Str + 1;
    140       }
    141     }
    142     A->setOwnsValues(true);
    143 
    144     return A;
    145   }
    146   case SeparateClass:
    147     // Matches iff this is an exact match.
    148     // FIXME: Avoid strlen.
    149     if (ArgSize != strlen(Args.getArgString(Index)))
    150       return 0;
    151 
    152     Index += 2;
    153     if (Index > Args.getNumInputArgStrings())
    154       return 0;
    155 
    156     return new Arg(UnaliasedOption, Spelling,
    157                    Index - 2, Args.getArgString(Index - 1));
    158   case MultiArgClass: {
    159     // Matches iff this is an exact match.
    160     // FIXME: Avoid strlen.
    161     if (ArgSize != strlen(Args.getArgString(Index)))
    162       return 0;
    163 
    164     Index += 1 + getNumArgs();
    165     if (Index > Args.getNumInputArgStrings())
    166       return 0;
    167 
    168     Arg *A = new Arg(UnaliasedOption, Spelling, Index - 1 - getNumArgs(),
    169                       Args.getArgString(Index - getNumArgs()));
    170     for (unsigned i = 1; i != getNumArgs(); ++i)
    171       A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
    172     return A;
    173   }
    174   case JoinedOrSeparateClass: {
    175     // If this is not an exact match, it is a joined arg.
    176     // FIXME: Avoid strlen.
    177     if (ArgSize != strlen(Args.getArgString(Index))) {
    178       const char *Value = Args.getArgString(Index) + ArgSize;
    179       return new Arg(*this, Spelling, Index++, Value);
    180     }
    181 
    182     // Otherwise it must be separate.
    183     Index += 2;
    184     if (Index > Args.getNumInputArgStrings())
    185       return 0;
    186 
    187     return new Arg(UnaliasedOption, Spelling,
    188                    Index - 2, Args.getArgString(Index - 1));
    189   }
    190   case JoinedAndSeparateClass:
    191     // Always matches.
    192     Index += 2;
    193     if (Index > Args.getNumInputArgStrings())
    194       return 0;
    195 
    196     return new Arg(UnaliasedOption, Spelling, Index - 2,
    197                    Args.getArgString(Index - 2) + ArgSize,
    198                    Args.getArgString(Index - 1));
    199   default:
    200     llvm_unreachable("Invalid option kind!");
    201   }
    202 }
    203