1249259Sdim//===--- Option.cpp - Abstract Driver Options -----------------------------===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim 10249259Sdim#include "llvm/Option/Option.h" 11249259Sdim#include "llvm/ADT/Twine.h" 12249259Sdim#include "llvm/Option/Arg.h" 13249259Sdim#include "llvm/Option/ArgList.h" 14249259Sdim#include "llvm/Support/ErrorHandling.h" 15249259Sdim#include "llvm/Support/raw_ostream.h" 16249259Sdim#include <algorithm> 17249259Sdim#include <cassert> 18249259Sdim 19249259Sdimusing namespace llvm; 20249259Sdimusing namespace llvm::opt; 21249259Sdim 22249259SdimOption::Option(const OptTable::Info *info, const OptTable *owner) 23249259Sdim : Info(info), Owner(owner) { 24249259Sdim 25249259Sdim // Multi-level aliases are not supported, and alias options cannot 26249259Sdim // have groups. This just simplifies option tracking, it is not an 27249259Sdim // inherent limitation. 28249259Sdim assert((!Info || !getAlias().isValid() || (!getAlias().getAlias().isValid() && 29249259Sdim !getGroup().isValid())) && 30249259Sdim "Multi-level aliases and aliases with groups are unsupported."); 31249259Sdim} 32249259Sdim 33249259SdimOption::~Option() { 34249259Sdim} 35249259Sdim 36249259Sdimvoid Option::dump() const { 37249259Sdim llvm::errs() << "<"; 38249259Sdim switch (getKind()) { 39249259Sdim#define P(N) case N: llvm::errs() << #N; break 40249259Sdim P(GroupClass); 41249259Sdim P(InputClass); 42249259Sdim P(UnknownClass); 43249259Sdim P(FlagClass); 44249259Sdim P(JoinedClass); 45249259Sdim P(SeparateClass); 46249259Sdim P(CommaJoinedClass); 47249259Sdim P(MultiArgClass); 48249259Sdim P(JoinedOrSeparateClass); 49249259Sdim P(JoinedAndSeparateClass); 50249259Sdim#undef P 51249259Sdim } 52249259Sdim 53249259Sdim llvm::errs() << " Prefixes:["; 54249259Sdim for (const char * const *Pre = Info->Prefixes; *Pre != 0; ++Pre) { 55249259Sdim llvm::errs() << '"' << *Pre << (*(Pre + 1) == 0 ? "\"" : "\", "); 56249259Sdim } 57249259Sdim llvm::errs() << ']'; 58249259Sdim 59249259Sdim llvm::errs() << " Name:\"" << getName() << '"'; 60249259Sdim 61249259Sdim const Option Group = getGroup(); 62249259Sdim if (Group.isValid()) { 63249259Sdim llvm::errs() << " Group:"; 64249259Sdim Group.dump(); 65249259Sdim } 66249259Sdim 67249259Sdim const Option Alias = getAlias(); 68249259Sdim if (Alias.isValid()) { 69249259Sdim llvm::errs() << " Alias:"; 70249259Sdim Alias.dump(); 71249259Sdim } 72249259Sdim 73249259Sdim if (getKind() == MultiArgClass) 74249259Sdim llvm::errs() << " NumArgs:" << getNumArgs(); 75249259Sdim 76249259Sdim llvm::errs() << ">\n"; 77249259Sdim} 78249259Sdim 79249259Sdimbool Option::matches(OptSpecifier Opt) const { 80249259Sdim // Aliases are never considered in matching, look through them. 81249259Sdim const Option Alias = getAlias(); 82249259Sdim if (Alias.isValid()) 83249259Sdim return Alias.matches(Opt); 84249259Sdim 85249259Sdim // Check exact match. 86249259Sdim if (getID() == Opt.getID()) 87249259Sdim return true; 88249259Sdim 89249259Sdim const Option Group = getGroup(); 90249259Sdim if (Group.isValid()) 91249259Sdim return Group.matches(Opt); 92249259Sdim return false; 93249259Sdim} 94249259Sdim 95249259SdimArg *Option::accept(const ArgList &Args, 96249259Sdim unsigned &Index, 97249259Sdim unsigned ArgSize) const { 98249259Sdim const Option &UnaliasedOption = getUnaliasedOption(); 99249259Sdim StringRef Spelling; 100249259Sdim // If the option was an alias, get the spelling from the unaliased one. 101249259Sdim if (getID() == UnaliasedOption.getID()) { 102249259Sdim Spelling = StringRef(Args.getArgString(Index), ArgSize); 103249259Sdim } else { 104249259Sdim Spelling = Args.MakeArgString(Twine(UnaliasedOption.getPrefix()) + 105249259Sdim Twine(UnaliasedOption.getName())); 106249259Sdim } 107249259Sdim 108249259Sdim switch (getKind()) { 109249259Sdim case FlagClass: 110249259Sdim if (ArgSize != strlen(Args.getArgString(Index))) 111249259Sdim return 0; 112249259Sdim 113249259Sdim return new Arg(UnaliasedOption, Spelling, Index++); 114249259Sdim case JoinedClass: { 115249259Sdim const char *Value = Args.getArgString(Index) + ArgSize; 116249259Sdim return new Arg(UnaliasedOption, Spelling, Index++, Value); 117249259Sdim } 118249259Sdim case CommaJoinedClass: { 119249259Sdim // Always matches. 120249259Sdim const char *Str = Args.getArgString(Index) + ArgSize; 121249259Sdim Arg *A = new Arg(UnaliasedOption, Spelling, Index++); 122249259Sdim 123249259Sdim // Parse out the comma separated values. 124249259Sdim const char *Prev = Str; 125249259Sdim for (;; ++Str) { 126249259Sdim char c = *Str; 127249259Sdim 128249259Sdim if (!c || c == ',') { 129249259Sdim if (Prev != Str) { 130249259Sdim char *Value = new char[Str - Prev + 1]; 131249259Sdim memcpy(Value, Prev, Str - Prev); 132249259Sdim Value[Str - Prev] = '\0'; 133249259Sdim A->getValues().push_back(Value); 134249259Sdim } 135249259Sdim 136249259Sdim if (!c) 137249259Sdim break; 138249259Sdim 139249259Sdim Prev = Str + 1; 140249259Sdim } 141249259Sdim } 142249259Sdim A->setOwnsValues(true); 143249259Sdim 144249259Sdim return A; 145249259Sdim } 146249259Sdim case SeparateClass: 147249259Sdim // Matches iff this is an exact match. 148249259Sdim // FIXME: Avoid strlen. 149249259Sdim if (ArgSize != strlen(Args.getArgString(Index))) 150249259Sdim return 0; 151249259Sdim 152249259Sdim Index += 2; 153249259Sdim if (Index > Args.getNumInputArgStrings()) 154249259Sdim return 0; 155249259Sdim 156249259Sdim return new Arg(UnaliasedOption, Spelling, 157249259Sdim Index - 2, Args.getArgString(Index - 1)); 158249259Sdim case MultiArgClass: { 159249259Sdim // Matches iff this is an exact match. 160249259Sdim // FIXME: Avoid strlen. 161249259Sdim if (ArgSize != strlen(Args.getArgString(Index))) 162249259Sdim return 0; 163249259Sdim 164249259Sdim Index += 1 + getNumArgs(); 165249259Sdim if (Index > Args.getNumInputArgStrings()) 166249259Sdim return 0; 167249259Sdim 168249259Sdim Arg *A = new Arg(UnaliasedOption, Spelling, Index - 1 - getNumArgs(), 169249259Sdim Args.getArgString(Index - getNumArgs())); 170249259Sdim for (unsigned i = 1; i != getNumArgs(); ++i) 171249259Sdim A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i)); 172249259Sdim return A; 173249259Sdim } 174249259Sdim case JoinedOrSeparateClass: { 175249259Sdim // If this is not an exact match, it is a joined arg. 176249259Sdim // FIXME: Avoid strlen. 177249259Sdim if (ArgSize != strlen(Args.getArgString(Index))) { 178249259Sdim const char *Value = Args.getArgString(Index) + ArgSize; 179249259Sdim return new Arg(*this, Spelling, Index++, Value); 180249259Sdim } 181249259Sdim 182249259Sdim // Otherwise it must be separate. 183249259Sdim Index += 2; 184249259Sdim if (Index > Args.getNumInputArgStrings()) 185249259Sdim return 0; 186249259Sdim 187249259Sdim return new Arg(UnaliasedOption, Spelling, 188249259Sdim Index - 2, Args.getArgString(Index - 1)); 189249259Sdim } 190249259Sdim case JoinedAndSeparateClass: 191249259Sdim // Always matches. 192249259Sdim Index += 2; 193249259Sdim if (Index > Args.getNumInputArgStrings()) 194249259Sdim return 0; 195249259Sdim 196249259Sdim return new Arg(UnaliasedOption, Spelling, Index - 2, 197249259Sdim Args.getArgString(Index - 2) + ArgSize, 198249259Sdim Args.getArgString(Index - 1)); 199249259Sdim default: 200249259Sdim llvm_unreachable("Invalid option kind!"); 201249259Sdim } 202249259Sdim} 203