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