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