1 //===- Option.cpp - Abstract Driver Options -------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
25 using namespace llvm::opt
;
27 Option::Option(const OptTable::Info
*info
, const OptTable
*owner
)
28 : 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.");
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.");
42 void Option::print(raw_ostream
&O
) const {
45 #define P(N) case N: O << #N; break
55 P(JoinedOrSeparateClass
);
56 P(JoinedAndSeparateClass
);
57 P(RemainingArgsClass
);
58 P(RemainingArgsJoinedClass
);
64 for (const char *const *Pre
= Info
->Prefixes
; *Pre
!= nullptr; ++Pre
) {
65 O
<< '"' << *Pre
<< (*(Pre
+ 1) == nullptr ? "\"" : "\", ");
70 O
<< " Name:\"" << getName() << '"';
72 const Option Group
= getGroup();
73 if (Group
.isValid()) {
78 const Option Alias
= getAlias();
79 if (Alias
.isValid()) {
84 if (getKind() == MultiArgClass
)
85 O
<< " NumArgs:" << getNumArgs();
90 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
91 LLVM_DUMP_METHOD
void Option::dump() const { print(dbgs()); }
94 bool Option::matches(OptSpecifier Opt
) const {
95 // Aliases are never considered in matching, look through them.
96 const Option Alias
= getAlias();
98 return Alias
.matches(Opt
);
100 // Check exact match.
101 if (getID() == Opt
.getID())
104 const Option Group
= getGroup();
106 return Group
.matches(Opt
);
110 Arg
*Option::accept(const ArgList
&Args
,
112 unsigned ArgSize
) const {
113 const Option
&UnaliasedOption
= getUnaliasedOption();
115 // If the option was an alias, get the spelling from the unaliased one.
116 if (getID() == UnaliasedOption
.getID()) {
117 Spelling
= StringRef(Args
.getArgString(Index
), ArgSize
);
119 Spelling
= Args
.MakeArgString(Twine(UnaliasedOption
.getPrefix()) +
120 Twine(UnaliasedOption
.getName()));
125 if (ArgSize
!= strlen(Args
.getArgString(Index
)))
128 Arg
*A
= new Arg(UnaliasedOption
, Spelling
, Index
++);
129 if (getAliasArgs()) {
130 const char *Val
= getAliasArgs();
131 while (*Val
!= '\0') {
132 A
->getValues().push_back(Val
);
134 // Move past the '\0' to the next argument.
135 Val
+= strlen(Val
) + 1;
139 if (UnaliasedOption
.getKind() == JoinedClass
&& !getAliasArgs())
140 // A Flag alias for a Joined option must provide an argument.
141 A
->getValues().push_back("");
146 const char *Value
= Args
.getArgString(Index
) + ArgSize
;
147 return new Arg(UnaliasedOption
, Spelling
, Index
++, Value
);
149 case CommaJoinedClass
: {
151 const char *Str
= Args
.getArgString(Index
) + ArgSize
;
152 Arg
*A
= new Arg(UnaliasedOption
, Spelling
, Index
++);
154 // Parse out the comma separated values.
155 const char *Prev
= Str
;
159 if (!c
|| c
== ',') {
161 char *Value
= new char[Str
- Prev
+ 1];
162 memcpy(Value
, Prev
, Str
- Prev
);
163 Value
[Str
- Prev
] = '\0';
164 A
->getValues().push_back(Value
);
173 A
->setOwnsValues(true);
178 // Matches iff this is an exact match.
179 // FIXME: Avoid strlen.
180 if (ArgSize
!= strlen(Args
.getArgString(Index
)))
184 if (Index
> Args
.getNumInputArgStrings() ||
185 Args
.getArgString(Index
- 1) == nullptr)
188 return new Arg(UnaliasedOption
, Spelling
,
189 Index
- 2, Args
.getArgString(Index
- 1));
190 case MultiArgClass
: {
191 // Matches iff this is an exact match.
192 // FIXME: Avoid strlen.
193 if (ArgSize
!= strlen(Args
.getArgString(Index
)))
196 Index
+= 1 + getNumArgs();
197 if (Index
> Args
.getNumInputArgStrings())
200 Arg
*A
= new Arg(UnaliasedOption
, Spelling
, Index
- 1 - getNumArgs(),
201 Args
.getArgString(Index
- getNumArgs()));
202 for (unsigned i
= 1; i
!= getNumArgs(); ++i
)
203 A
->getValues().push_back(Args
.getArgString(Index
- getNumArgs() + i
));
206 case JoinedOrSeparateClass
: {
207 // If this is not an exact match, it is a joined arg.
208 // FIXME: Avoid strlen.
209 if (ArgSize
!= strlen(Args
.getArgString(Index
))) {
210 const char *Value
= Args
.getArgString(Index
) + ArgSize
;
211 return new Arg(*this, Spelling
, Index
++, Value
);
214 // Otherwise it must be separate.
216 if (Index
> Args
.getNumInputArgStrings() ||
217 Args
.getArgString(Index
- 1) == nullptr)
220 return new Arg(UnaliasedOption
, Spelling
,
221 Index
- 2, Args
.getArgString(Index
- 1));
223 case JoinedAndSeparateClass
:
226 if (Index
> Args
.getNumInputArgStrings() ||
227 Args
.getArgString(Index
- 1) == nullptr)
230 return new Arg(UnaliasedOption
, Spelling
, Index
- 2,
231 Args
.getArgString(Index
- 2) + ArgSize
,
232 Args
.getArgString(Index
- 1));
233 case RemainingArgsClass
: {
234 // Matches iff this is an exact match.
235 // FIXME: Avoid strlen.
236 if (ArgSize
!= strlen(Args
.getArgString(Index
)))
238 Arg
*A
= new Arg(UnaliasedOption
, Spelling
, Index
++);
239 while (Index
< Args
.getNumInputArgStrings() &&
240 Args
.getArgString(Index
) != nullptr)
241 A
->getValues().push_back(Args
.getArgString(Index
++));
244 case RemainingArgsJoinedClass
: {
245 Arg
*A
= new Arg(UnaliasedOption
, Spelling
, Index
);
246 if (ArgSize
!= strlen(Args
.getArgString(Index
))) {
247 // An inexact match means there is a joined arg.
248 A
->getValues().push_back(Args
.getArgString(Index
) + ArgSize
);
251 while (Index
< Args
.getNumInputArgStrings() &&
252 Args
.getArgString(Index
) != nullptr)
253 A
->getValues().push_back(Args
.getArgString(Index
++));
258 llvm_unreachable("Invalid option kind!");