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