blob: 4832e659f026dac4b6cf21dadd8e08c3f353bdb0 [file] [log] [blame]
Eugene Zelenkoaf615892017-06-16 00:43:26 +00001//===- Option.cpp - Abstract Driver Options -------------------------------===//
Michael J. Spencer41ee0412012-12-05 00:29:32 +00002//
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
Eugene Zelenkoaf615892017-06-16 00:43:26 +000010#include "llvm/ADT/StringRef.h"
Michael J. Spencer41ee0412012-12-05 00:29:32 +000011#include "llvm/ADT/Twine.h"
12#include "llvm/Option/Arg.h"
13#include "llvm/Option/ArgList.h"
Eugene Zelenkoaf615892017-06-16 00:43:26 +000014#include "llvm/Option/Option.h"
15#include "llvm/Option/OptTable.h"
16#include "llvm/Support/Compiler.h"
Eric Christopher9a8b5e72015-12-18 18:55:26 +000017#include "llvm/Support/Debug.h"
Michael J. Spencer41ee0412012-12-05 00:29:32 +000018#include "llvm/Support/ErrorHandling.h"
Chandler Carruthbe810232013-01-02 10:22:59 +000019#include "llvm/Support/raw_ostream.h"
Michael J. Spencer41ee0412012-12-05 00:29:32 +000020#include <cassert>
Eugene Zelenkoaf615892017-06-16 00:43:26 +000021#include <cstring>
Michael J. Spencer41ee0412012-12-05 00:29:32 +000022
23using namespace llvm;
24using namespace llvm::opt;
25
26Option::Option(const OptTable::Info *info, const OptTable *owner)
27 : Info(info), Owner(owner) {
Hans Wennborg31d6fd82013-07-22 16:18:13 +000028 // Multi-level aliases are not supported. This just simplifies option
29 // tracking, it is not an inherent limitation.
Richard Trieu46978d42013-07-22 21:29:28 +000030 assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) &&
Hans Wennborg31d6fd82013-07-22 16:18:13 +000031 "Multi-level aliases are not supported.");
Hans Wennborg5fdcf862013-07-31 22:44:41 +000032
33 if (Info && getAliasArgs()) {
34 assert(getAlias().isValid() && "Only alias options can have alias args.");
35 assert(getKind() == FlagClass && "Only Flag aliases can have alias args.");
36 assert(getAlias().getKind() != FlagClass &&
37 "Cannot provide alias args to a flag option.");
38 }
Michael J. Spencer41ee0412012-12-05 00:29:32 +000039}
40
Eric Christopher9a8b5e72015-12-18 18:55:26 +000041void Option::print(raw_ostream &O) const {
42 O << "<";
Michael J. Spencer41ee0412012-12-05 00:29:32 +000043 switch (getKind()) {
Eric Christopher9a8b5e72015-12-18 18:55:26 +000044#define P(N) case N: O << #N; break
Michael J. Spencer41ee0412012-12-05 00:29:32 +000045 P(GroupClass);
46 P(InputClass);
47 P(UnknownClass);
48 P(FlagClass);
49 P(JoinedClass);
50 P(SeparateClass);
51 P(CommaJoinedClass);
52 P(MultiArgClass);
53 P(JoinedOrSeparateClass);
54 P(JoinedAndSeparateClass);
Hans Wennborgd505fbf2013-08-13 21:09:50 +000055 P(RemainingArgsClass);
Hans Wennborg40cfde32016-04-15 00:23:30 +000056 P(RemainingArgsJoinedClass);
Michael J. Spencer41ee0412012-12-05 00:29:32 +000057#undef P
58 }
59
Reid Kleckner7b78d352013-06-26 22:43:37 +000060 if (Info->Prefixes) {
Eric Christopher9a8b5e72015-12-18 18:55:26 +000061 O << " Prefixes:[";
62 for (const char *const *Pre = Info->Prefixes; *Pre != nullptr; ++Pre) {
63 O << '"' << *Pre << (*(Pre + 1) == nullptr ? "\"" : "\", ");
Reid Kleckner7b78d352013-06-26 22:43:37 +000064 }
Eric Christopher9a8b5e72015-12-18 18:55:26 +000065 O << ']';
Michael J. Spencer41ee0412012-12-05 00:29:32 +000066 }
Michael J. Spencer41ee0412012-12-05 00:29:32 +000067
Eric Christopher9a8b5e72015-12-18 18:55:26 +000068 O << " Name:\"" << getName() << '"';
Michael J. Spencer41ee0412012-12-05 00:29:32 +000069
70 const Option Group = getGroup();
71 if (Group.isValid()) {
Eric Christopher9a8b5e72015-12-18 18:55:26 +000072 O << " Group:";
73 Group.print(O);
Michael J. Spencer41ee0412012-12-05 00:29:32 +000074 }
75
76 const Option Alias = getAlias();
77 if (Alias.isValid()) {
Eric Christopher9a8b5e72015-12-18 18:55:26 +000078 O << " Alias:";
79 Alias.print(O);
Michael J. Spencer41ee0412012-12-05 00:29:32 +000080 }
81
82 if (getKind() == MultiArgClass)
Eric Christopher9a8b5e72015-12-18 18:55:26 +000083 O << " NumArgs:" << getNumArgs();
Michael J. Spencer41ee0412012-12-05 00:29:32 +000084
Eric Christopher9a8b5e72015-12-18 18:55:26 +000085 O << ">\n";
Michael J. Spencer41ee0412012-12-05 00:29:32 +000086}
87
Matthias Braun8c209aa2017-01-28 02:02:38 +000088#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
Yaron Kereneb2a2542016-01-29 20:50:44 +000089LLVM_DUMP_METHOD void Option::dump() const { print(dbgs()); }
Matthias Braun8c209aa2017-01-28 02:02:38 +000090#endif
Eric Christopher9a8b5e72015-12-18 18:55:26 +000091
Michael J. Spencer41ee0412012-12-05 00:29:32 +000092bool Option::matches(OptSpecifier Opt) const {
93 // Aliases are never considered in matching, look through them.
94 const Option Alias = getAlias();
95 if (Alias.isValid())
96 return Alias.matches(Opt);
97
98 // Check exact match.
99 if (getID() == Opt.getID())
100 return true;
101
102 const Option Group = getGroup();
103 if (Group.isValid())
104 return Group.matches(Opt);
105 return false;
106}
107
108Arg *Option::accept(const ArgList &Args,
109 unsigned &Index,
110 unsigned ArgSize) const {
111 const Option &UnaliasedOption = getUnaliasedOption();
112 StringRef Spelling;
113 // If the option was an alias, get the spelling from the unaliased one.
114 if (getID() == UnaliasedOption.getID()) {
115 Spelling = StringRef(Args.getArgString(Index), ArgSize);
116 } else {
117 Spelling = Args.MakeArgString(Twine(UnaliasedOption.getPrefix()) +
118 Twine(UnaliasedOption.getName()));
119 }
120
121 switch (getKind()) {
Hans Wennborg5fdcf862013-07-31 22:44:41 +0000122 case FlagClass: {
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000123 if (ArgSize != strlen(Args.getArgString(Index)))
Craig Topper2617dcc2014-04-15 06:32:26 +0000124 return nullptr;
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000125
Hans Wennborg5fdcf862013-07-31 22:44:41 +0000126 Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
127 if (getAliasArgs()) {
128 const char *Val = getAliasArgs();
129 while (*Val != '\0') {
130 A->getValues().push_back(Val);
131
132 // Move past the '\0' to the next argument.
133 Val += strlen(Val) + 1;
134 }
135 }
Hans Wennborg8d8146f2015-05-04 18:00:13 +0000136
137 if (UnaliasedOption.getKind() == JoinedClass && !getAliasArgs())
138 // A Flag alias for a Joined option must provide an argument.
139 A->getValues().push_back("");
140
Hans Wennborg5fdcf862013-07-31 22:44:41 +0000141 return A;
142 }
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000143 case JoinedClass: {
144 const char *Value = Args.getArgString(Index) + ArgSize;
145 return new Arg(UnaliasedOption, Spelling, Index++, Value);
146 }
147 case CommaJoinedClass: {
148 // Always matches.
149 const char *Str = Args.getArgString(Index) + ArgSize;
150 Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
151
152 // Parse out the comma separated values.
153 const char *Prev = Str;
154 for (;; ++Str) {
155 char c = *Str;
156
157 if (!c || c == ',') {
158 if (Prev != Str) {
159 char *Value = new char[Str - Prev + 1];
160 memcpy(Value, Prev, Str - Prev);
161 Value[Str - Prev] = '\0';
162 A->getValues().push_back(Value);
163 }
164
165 if (!c)
166 break;
167
168 Prev = Str + 1;
169 }
170 }
171 A->setOwnsValues(true);
172
173 return A;
174 }
175 case SeparateClass:
176 // Matches iff this is an exact match.
177 // FIXME: Avoid strlen.
178 if (ArgSize != strlen(Args.getArgString(Index)))
Craig Topper2617dcc2014-04-15 06:32:26 +0000179 return nullptr;
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000180
181 Index += 2;
Reid Klecknere3f146d2014-08-22 19:29:17 +0000182 if (Index > Args.getNumInputArgStrings() ||
183 Args.getArgString(Index - 1) == nullptr)
Craig Topper2617dcc2014-04-15 06:32:26 +0000184 return nullptr;
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000185
186 return new Arg(UnaliasedOption, Spelling,
187 Index - 2, Args.getArgString(Index - 1));
188 case MultiArgClass: {
189 // Matches iff this is an exact match.
190 // FIXME: Avoid strlen.
191 if (ArgSize != strlen(Args.getArgString(Index)))
Craig Topper2617dcc2014-04-15 06:32:26 +0000192 return nullptr;
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000193
194 Index += 1 + getNumArgs();
195 if (Index > Args.getNumInputArgStrings())
Craig Topper2617dcc2014-04-15 06:32:26 +0000196 return nullptr;
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000197
198 Arg *A = new Arg(UnaliasedOption, Spelling, Index - 1 - getNumArgs(),
199 Args.getArgString(Index - getNumArgs()));
200 for (unsigned i = 1; i != getNumArgs(); ++i)
201 A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
202 return A;
203 }
204 case JoinedOrSeparateClass: {
205 // If this is not an exact match, it is a joined arg.
206 // FIXME: Avoid strlen.
207 if (ArgSize != strlen(Args.getArgString(Index))) {
208 const char *Value = Args.getArgString(Index) + ArgSize;
209 return new Arg(*this, Spelling, Index++, Value);
210 }
211
212 // Otherwise it must be separate.
213 Index += 2;
Reid Klecknere3f146d2014-08-22 19:29:17 +0000214 if (Index > Args.getNumInputArgStrings() ||
215 Args.getArgString(Index - 1) == nullptr)
Craig Topper2617dcc2014-04-15 06:32:26 +0000216 return nullptr;
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000217
218 return new Arg(UnaliasedOption, Spelling,
219 Index - 2, Args.getArgString(Index - 1));
220 }
221 case JoinedAndSeparateClass:
222 // Always matches.
223 Index += 2;
Reid Klecknere3f146d2014-08-22 19:29:17 +0000224 if (Index > Args.getNumInputArgStrings() ||
225 Args.getArgString(Index - 1) == nullptr)
Craig Topper2617dcc2014-04-15 06:32:26 +0000226 return nullptr;
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000227
228 return new Arg(UnaliasedOption, Spelling, Index - 2,
229 Args.getArgString(Index - 2) + ArgSize,
230 Args.getArgString(Index - 1));
Hans Wennborgd505fbf2013-08-13 21:09:50 +0000231 case RemainingArgsClass: {
232 // Matches iff this is an exact match.
233 // FIXME: Avoid strlen.
234 if (ArgSize != strlen(Args.getArgString(Index)))
Craig Topper2617dcc2014-04-15 06:32:26 +0000235 return nullptr;
Hans Wennborgd505fbf2013-08-13 21:09:50 +0000236 Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
Reid Klecknere3f146d2014-08-22 19:29:17 +0000237 while (Index < Args.getNumInputArgStrings() &&
238 Args.getArgString(Index) != nullptr)
Hans Wennborgd505fbf2013-08-13 21:09:50 +0000239 A->getValues().push_back(Args.getArgString(Index++));
240 return A;
241 }
Hans Wennborg40cfde32016-04-15 00:23:30 +0000242 case RemainingArgsJoinedClass: {
243 Arg *A = new Arg(UnaliasedOption, Spelling, Index);
244 if (ArgSize != strlen(Args.getArgString(Index))) {
245 // An inexact match means there is a joined arg.
246 A->getValues().push_back(Args.getArgString(Index) + ArgSize);
247 }
248 Index++;
249 while (Index < Args.getNumInputArgStrings() &&
250 Args.getArgString(Index) != nullptr)
251 A->getValues().push_back(Args.getArgString(Index++));
252 return A;
253 }
254
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000255 default:
256 llvm_unreachable("Invalid option kind!");
257 }
258}