Line data Source code
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/ADT/StringRef.h"
11 : #include "llvm/ADT/Twine.h"
12 : #include "llvm/Config/llvm-config.h"
13 : #include "llvm/Option/Arg.h"
14 : #include "llvm/Option/ArgList.h"
15 : #include "llvm/Option/Option.h"
16 : #include "llvm/Option/OptTable.h"
17 : #include "llvm/Support/Compiler.h"
18 : #include "llvm/Support/Debug.h"
19 : #include "llvm/Support/ErrorHandling.h"
20 : #include "llvm/Support/raw_ostream.h"
21 : #include <cassert>
22 : #include <cstring>
23 :
24 : using namespace llvm;
25 : using namespace llvm::opt;
26 :
27 215318584 : Option::Option(const OptTable::Info *info, const OptTable *owner)
28 215318584 : : Info(info), Owner(owner) {
29 : // Multi-level aliases are not supported. This just simplifies option
30 : // tracking, it is not an inherent limitation.
31 : assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) &&
32 : "Multi-level aliases are not supported.");
33 :
34 : if (Info && getAliasArgs()) {
35 : assert(getAlias().isValid() && "Only alias options can have alias args.");
36 : assert(getKind() == FlagClass && "Only Flag aliases can have alias args.");
37 : assert(getAlias().getKind() != FlagClass &&
38 : "Cannot provide alias args to a flag option.");
39 : }
40 215318584 : }
41 :
42 0 : void Option::print(raw_ostream &O) const {
43 0 : O << "<";
44 0 : switch (getKind()) {
45 : #define P(N) case N: O << #N; break
46 0 : P(GroupClass);
47 0 : P(InputClass);
48 0 : P(UnknownClass);
49 0 : P(FlagClass);
50 0 : P(JoinedClass);
51 0 : P(ValuesClass);
52 0 : P(SeparateClass);
53 0 : P(CommaJoinedClass);
54 0 : P(MultiArgClass);
55 0 : P(JoinedOrSeparateClass);
56 0 : P(JoinedAndSeparateClass);
57 0 : P(RemainingArgsClass);
58 0 : P(RemainingArgsJoinedClass);
59 : #undef P
60 : }
61 :
62 0 : if (Info->Prefixes) {
63 0 : O << " Prefixes:[";
64 0 : for (const char *const *Pre = Info->Prefixes; *Pre != nullptr; ++Pre) {
65 0 : O << '"' << *Pre << (*(Pre + 1) == nullptr ? "\"" : "\", ");
66 : }
67 : O << ']';
68 : }
69 :
70 0 : O << " Name:\"" << getName() << '"';
71 :
72 0 : const Option Group = getGroup();
73 0 : if (Group.isValid()) {
74 0 : O << " Group:";
75 0 : Group.print(O);
76 : }
77 :
78 0 : const Option Alias = getAlias();
79 0 : if (Alias.isValid()) {
80 0 : O << " Alias:";
81 0 : Alias.print(O);
82 : }
83 :
84 0 : if (getKind() == MultiArgClass)
85 0 : O << " NumArgs:" << getNumArgs();
86 :
87 0 : O << ">\n";
88 0 : }
89 :
90 : #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
91 : LLVM_DUMP_METHOD void Option::dump() const { print(dbgs()); }
92 : #endif
93 :
94 99880941 : bool Option::matches(OptSpecifier Opt) const {
95 : // Aliases are never considered in matching, look through them.
96 99880941 : const Option Alias = getAlias();
97 99880943 : if (Alias.isValid())
98 3565 : return Alias.matches(Opt);
99 :
100 : // Check exact match.
101 199754756 : if (getID() == Opt.getID())
102 : return true;
103 :
104 96830072 : const Option Group = getGroup();
105 96830095 : if (Group.isValid())
106 61420353 : return Group.matches(Opt);
107 : return false;
108 : }
109 :
110 2604509 : Arg *Option::accept(const ArgList &Args,
111 : unsigned &Index,
112 : unsigned ArgSize) const {
113 2604509 : const Option &UnaliasedOption = getUnaliasedOption();
114 : StringRef Spelling;
115 : // If the option was an alias, get the spelling from the unaliased one.
116 5209018 : if (getID() == UnaliasedOption.getID()) {
117 2579701 : Spelling = StringRef(Args.getArgString(Index), ArgSize);
118 : } else {
119 49616 : Spelling = Args.MakeArgString(Twine(UnaliasedOption.getPrefix()) +
120 49616 : Twine(UnaliasedOption.getName()));
121 : }
122 :
123 5209016 : switch (getKind()) {
124 482302 : case FlagClass: {
125 482302 : if (ArgSize != strlen(Args.getArgString(Index)))
126 : return nullptr;
127 :
128 480536 : Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
129 961074 : if (getAliasArgs()) {
130 1158 : const char *Val = getAliasArgs();
131 2316 : while (*Val != '\0') {
132 1158 : A->getValues().push_back(Val);
133 :
134 : // Move past the '\0' to the next argument.
135 1158 : Val += strlen(Val) + 1;
136 : }
137 : }
138 :
139 480537 : if (UnaliasedOption.getKind() == JoinedClass && !getAliasArgs())
140 : // A Flag alias for a Joined option must provide an argument.
141 1 : A->getValues().push_back("");
142 :
143 : return A;
144 : }
145 439960 : case JoinedClass: {
146 439960 : const char *Value = Args.getArgString(Index) + ArgSize;
147 439960 : return new Arg(UnaliasedOption, Spelling, Index++, Value);
148 : }
149 28755 : case CommaJoinedClass: {
150 : // Always matches.
151 28755 : const char *Str = Args.getArgString(Index) + ArgSize;
152 28755 : Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
153 :
154 : // Parse out the comma separated values.
155 : const char *Prev = Str;
156 1610785 : for (;; ++Str) {
157 1639540 : char c = *Str;
158 :
159 1639540 : if (!c || c == ',') {
160 51415 : if (Prev != Str) {
161 51407 : char *Value = new char[Str - Prev + 1];
162 51407 : memcpy(Value, Prev, Str - Prev);
163 51407 : Value[Str - Prev] = '\0';
164 51407 : A->getValues().push_back(Value);
165 : }
166 :
167 51415 : if (!c)
168 : break;
169 :
170 22660 : Prev = Str + 1;
171 : }
172 1610785 : }
173 : A->setOwnsValues(true);
174 :
175 28755 : return A;
176 : }
177 178723 : case SeparateClass:
178 : // Matches iff this is an exact match.
179 : // FIXME: Avoid strlen.
180 178723 : if (ArgSize != strlen(Args.getArgString(Index)))
181 : return nullptr;
182 :
183 178721 : Index += 2;
184 357438 : if (Index > Args.getNumInputArgStrings() ||
185 178717 : Args.getArgString(Index - 1) == nullptr)
186 4 : return nullptr;
187 :
188 : return new Arg(UnaliasedOption, Spelling,
189 178717 : Index - 2, Args.getArgString(Index - 1));
190 6 : case MultiArgClass: {
191 : // Matches iff this is an exact match.
192 : // FIXME: Avoid strlen.
193 6 : if (ArgSize != strlen(Args.getArgString(Index)))
194 : return nullptr;
195 :
196 6 : Index += 1 + getNumArgs();
197 6 : if (Index > Args.getNumInputArgStrings())
198 : return nullptr;
199 :
200 12 : Arg *A = new Arg(UnaliasedOption, Spelling, Index - 1 - getNumArgs(),
201 12 : Args.getArgString(Index - getNumArgs()));
202 32 : for (unsigned i = 1; i != getNumArgs(); ++i)
203 10 : A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
204 : return A;
205 : }
206 1473828 : case JoinedOrSeparateClass: {
207 : // If this is not an exact match, it is a joined arg.
208 : // FIXME: Avoid strlen.
209 1473828 : if (ArgSize != strlen(Args.getArgString(Index))) {
210 896235 : const char *Value = Args.getArgString(Index) + ArgSize;
211 896235 : return new Arg(*this, Spelling, Index++, Value);
212 : }
213 :
214 : // Otherwise it must be separate.
215 577593 : Index += 2;
216 1155176 : if (Index > Args.getNumInputArgStrings() ||
217 577583 : Args.getArgString(Index - 1) == nullptr)
218 10 : return nullptr;
219 :
220 : return new Arg(UnaliasedOption, Spelling,
221 577583 : Index - 2, Args.getArgString(Index - 1));
222 : }
223 27 : case JoinedAndSeparateClass:
224 : // Always matches.
225 27 : Index += 2;
226 54 : if (Index > Args.getNumInputArgStrings() ||
227 27 : Args.getArgString(Index - 1) == nullptr)
228 0 : return nullptr;
229 :
230 27 : return new Arg(UnaliasedOption, Spelling, Index - 2,
231 54 : Args.getArgString(Index - 2) + ArgSize,
232 27 : Args.getArgString(Index - 1));
233 893 : case RemainingArgsClass: {
234 : // Matches iff this is an exact match.
235 : // FIXME: Avoid strlen.
236 893 : if (ArgSize != strlen(Args.getArgString(Index)))
237 : return nullptr;
238 888 : Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
239 2718 : while (Index < Args.getNumInputArgStrings() &&
240 915 : Args.getArgString(Index) != nullptr)
241 915 : A->getValues().push_back(Args.getArgString(Index++));
242 : return A;
243 : }
244 14 : case RemainingArgsJoinedClass: {
245 14 : Arg *A = new Arg(UnaliasedOption, Spelling, Index);
246 14 : if (ArgSize != strlen(Args.getArgString(Index))) {
247 : // An inexact match means there is a joined arg.
248 4 : A->getValues().push_back(Args.getArgString(Index) + ArgSize);
249 : }
250 14 : Index++;
251 62 : while (Index < Args.getNumInputArgStrings() &&
252 25 : Args.getArgString(Index) != nullptr)
253 23 : A->getValues().push_back(Args.getArgString(Index++));
254 : return A;
255 : }
256 :
257 0 : default:
258 0 : llvm_unreachable("Invalid option kind!");
259 : }
260 : }
|