1218893Sdim//===--- Option.cpp - Abstract Driver Options -----------------------------===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed 10193326Sed#include "clang/Driver/Option.h" 11193326Sed#include "clang/Driver/Arg.h" 12193326Sed#include "clang/Driver/ArgList.h" 13249423Sdim#include "llvm/ADT/Twine.h" 14249423Sdim#include "llvm/Support/ErrorHandling.h" 15193326Sed#include "llvm/Support/raw_ostream.h" 16249423Sdim#include <algorithm> 17193326Sed#include <cassert> 18193326Sedusing namespace clang::driver; 19193326Sed 20243830SdimOption::Option(const OptTable::Info *info, const OptTable *owner) 21243830Sdim : Info(info), Owner(owner) { 22193326Sed 23193326Sed // Multi-level aliases are not supported, and alias options cannot 24193326Sed // have groups. This just simplifies option tracking, it is not an 25193326Sed // inherent limitation. 26243830Sdim assert((!Info || !getAlias().isValid() || (!getAlias().getAlias().isValid() && 27243830Sdim !getGroup().isValid())) && 28198092Srdivacky "Multi-level aliases and aliases with groups are unsupported."); 29193326Sed} 30193326Sed 31193326SedOption::~Option() { 32193326Sed} 33193326Sed 34193326Sedvoid Option::dump() const { 35193326Sed llvm::errs() << "<"; 36243830Sdim switch (getKind()) { 37193326Sed#define P(N) case N: llvm::errs() << #N; break 38193326Sed P(GroupClass); 39193326Sed P(InputClass); 40193326Sed P(UnknownClass); 41193326Sed P(FlagClass); 42193326Sed P(JoinedClass); 43193326Sed P(SeparateClass); 44193326Sed P(CommaJoinedClass); 45193326Sed P(MultiArgClass); 46193326Sed P(JoinedOrSeparateClass); 47193326Sed P(JoinedAndSeparateClass); 48193326Sed#undef P 49193326Sed } 50193326Sed 51243830Sdim llvm::errs() << " Prefixes:["; 52243830Sdim for (const char * const *Pre = Info->Prefixes; *Pre != 0; ++Pre) { 53243830Sdim llvm::errs() << '"' << *Pre << (*(Pre + 1) == 0 ? "\"" : "\", "); 54243830Sdim } 55243830Sdim llvm::errs() << ']'; 56193326Sed 57243830Sdim llvm::errs() << " Name:\"" << getName() << '"'; 58243830Sdim 59243830Sdim const Option Group = getGroup(); 60243830Sdim if (Group.isValid()) { 61193326Sed llvm::errs() << " Group:"; 62243830Sdim Group.dump(); 63193326Sed } 64198092Srdivacky 65243830Sdim const Option Alias = getAlias(); 66243830Sdim if (Alias.isValid()) { 67193326Sed llvm::errs() << " Alias:"; 68243830Sdim Alias.dump(); 69193326Sed } 70198092Srdivacky 71243830Sdim if (getKind() == MultiArgClass) 72243830Sdim llvm::errs() << " NumArgs:" << getNumArgs(); 73193326Sed 74193326Sed llvm::errs() << ">\n"; 75193326Sed} 76193326Sed 77199512Srdivackybool Option::matches(OptSpecifier Opt) const { 78199512Srdivacky // Aliases are never considered in matching, look through them. 79243830Sdim const Option Alias = getAlias(); 80243830Sdim if (Alias.isValid()) 81243830Sdim return Alias.matches(Opt); 82198092Srdivacky 83199512Srdivacky // Check exact match. 84243830Sdim if (getID() == Opt.getID()) 85193326Sed return true; 86198092Srdivacky 87243830Sdim const Option Group = getGroup(); 88243830Sdim if (Group.isValid()) 89243830Sdim return Group.matches(Opt); 90193326Sed return false; 91193326Sed} 92193326Sed 93243830SdimArg *Option::accept(const ArgList &Args, 94243830Sdim unsigned &Index, 95243830Sdim unsigned ArgSize) const { 96243830Sdim const Option &UnaliasedOption = getUnaliasedOption(); 97243830Sdim StringRef Spelling; 98243830Sdim // If the option was an alias, get the spelling from the unaliased one. 99243830Sdim if (getID() == UnaliasedOption.getID()) { 100243830Sdim Spelling = StringRef(Args.getArgString(Index), ArgSize); 101243830Sdim } else { 102243830Sdim Spelling = Args.MakeArgString(Twine(UnaliasedOption.getPrefix()) + 103243830Sdim Twine(UnaliasedOption.getName())); 104243830Sdim } 105193326Sed 106243830Sdim switch (getKind()) { 107243830Sdim case FlagClass: 108243830Sdim if (ArgSize != strlen(Args.getArgString(Index))) 109243830Sdim return 0; 110193326Sed 111243830Sdim return new Arg(UnaliasedOption, Spelling, Index++); 112243830Sdim case JoinedClass: { 113243830Sdim const char *Value = Args.getArgString(Index) + ArgSize; 114243830Sdim return new Arg(UnaliasedOption, Spelling, Index++, Value); 115243830Sdim } 116243830Sdim case CommaJoinedClass: { 117243830Sdim // Always matches. 118243830Sdim const char *Str = Args.getArgString(Index) + ArgSize; 119243830Sdim Arg *A = new Arg(UnaliasedOption, Spelling, Index++); 120193326Sed 121243830Sdim // Parse out the comma separated values. 122243830Sdim const char *Prev = Str; 123243830Sdim for (;; ++Str) { 124243830Sdim char c = *Str; 125193326Sed 126243830Sdim if (!c || c == ',') { 127243830Sdim if (Prev != Str) { 128243830Sdim char *Value = new char[Str - Prev + 1]; 129243830Sdim memcpy(Value, Prev, Str - Prev); 130243830Sdim Value[Str - Prev] = '\0'; 131243830Sdim A->getValues().push_back(Value); 132243830Sdim } 133193326Sed 134243830Sdim if (!c) 135243830Sdim break; 136193326Sed 137243830Sdim Prev = Str + 1; 138210299Sed } 139243830Sdim } 140243830Sdim A->setOwnsValues(true); 141210299Sed 142243830Sdim return A; 143210299Sed } 144243830Sdim case SeparateClass: 145243830Sdim // Matches iff this is an exact match. 146243830Sdim // FIXME: Avoid strlen. 147243830Sdim if (ArgSize != strlen(Args.getArgString(Index))) 148243830Sdim return 0; 149210299Sed 150243830Sdim Index += 2; 151243830Sdim if (Index > Args.getNumInputArgStrings()) 152243830Sdim return 0; 153193326Sed 154243830Sdim return new Arg(UnaliasedOption, Spelling, 155243830Sdim Index - 2, Args.getArgString(Index - 1)); 156243830Sdim case MultiArgClass: { 157243830Sdim // Matches iff this is an exact match. 158243830Sdim // FIXME: Avoid strlen. 159243830Sdim if (ArgSize != strlen(Args.getArgString(Index))) 160243830Sdim return 0; 161193326Sed 162243830Sdim Index += 1 + getNumArgs(); 163243830Sdim if (Index > Args.getNumInputArgStrings()) 164243830Sdim return 0; 165193326Sed 166243830Sdim Arg *A = new Arg(UnaliasedOption, Spelling, Index - 1 - getNumArgs(), 167243830Sdim Args.getArgString(Index - getNumArgs())); 168243830Sdim for (unsigned i = 1; i != getNumArgs(); ++i) 169243830Sdim A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i)); 170243830Sdim return A; 171243830Sdim } 172243830Sdim case JoinedOrSeparateClass: { 173243830Sdim // If this is not an exact match, it is a joined arg. 174243830Sdim // FIXME: Avoid strlen. 175243830Sdim if (ArgSize != strlen(Args.getArgString(Index))) { 176243830Sdim const char *Value = Args.getArgString(Index) + ArgSize; 177243830Sdim return new Arg(*this, Spelling, Index++, Value); 178243830Sdim } 179193326Sed 180243830Sdim // Otherwise it must be separate. 181243830Sdim Index += 2; 182243830Sdim if (Index > Args.getNumInputArgStrings()) 183243830Sdim return 0; 184193326Sed 185243830Sdim return new Arg(UnaliasedOption, Spelling, 186243830Sdim Index - 2, Args.getArgString(Index - 1)); 187243830Sdim } 188243830Sdim case JoinedAndSeparateClass: 189243830Sdim // Always matches. 190243830Sdim Index += 2; 191243830Sdim if (Index > Args.getNumInputArgStrings()) 192243830Sdim return 0; 193193326Sed 194243830Sdim return new Arg(UnaliasedOption, Spelling, Index - 2, 195243830Sdim Args.getArgString(Index - 2) + ArgSize, 196243830Sdim Args.getArgString(Index - 1)); 197243830Sdim default: 198243830Sdim llvm_unreachable("Invalid option kind!"); 199210299Sed } 200193326Sed} 201