blob: 221414d79e77925650ca8c891058f3b3cc27624c [file] [log] [blame]
Michael J. Spencer41ee0412012-12-05 00:29:32 +00001//===--- 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"
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"
Michael J. Spencer41ee0412012-12-05 00:29:32 +000014#include "llvm/Support/ErrorHandling.h"
Chandler Carruthbe810232013-01-02 10:22:59 +000015#include "llvm/Support/raw_ostream.h"
Michael J. Spencer41ee0412012-12-05 00:29:32 +000016#include <algorithm>
17#include <cassert>
18
19using namespace llvm;
20using namespace llvm::opt;
21
22Option::Option(const OptTable::Info *info, const OptTable *owner)
23 : Info(info), Owner(owner) {
24
Hans Wennborg31d6fd82013-07-22 16:18:13 +000025 // Multi-level aliases are not supported. This just simplifies option
26 // tracking, it is not an inherent limitation.
Richard Trieu46978d42013-07-22 21:29:28 +000027 assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) &&
Hans Wennborg31d6fd82013-07-22 16:18:13 +000028 "Multi-level aliases are not supported.");
Hans Wennborg5fdcf862013-07-31 22:44:41 +000029
30 if (Info && getAliasArgs()) {
31 assert(getAlias().isValid() && "Only alias options can have alias args.");
32 assert(getKind() == FlagClass && "Only Flag aliases can have alias args.");
33 assert(getAlias().getKind() != FlagClass &&
34 "Cannot provide alias args to a flag option.");
35 }
Michael J. Spencer41ee0412012-12-05 00:29:32 +000036}
37
Michael J. Spencer41ee0412012-12-05 00:29:32 +000038void 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);
Hans Wennborgd505fbf2013-08-13 21:09:50 +000052 P(RemainingArgsClass);
Michael J. Spencer41ee0412012-12-05 00:29:32 +000053#undef P
54 }
55
Reid Kleckner7b78d352013-06-26 22:43:37 +000056 if (Info->Prefixes) {
57 llvm::errs() << " Prefixes:[";
Craig Topper2617dcc2014-04-15 06:32:26 +000058 for (const char * const *Pre = Info->Prefixes; *Pre != nullptr; ++Pre) {
59 llvm::errs() << '"' << *Pre << (*(Pre + 1) == nullptr ? "\"" : "\", ");
Reid Kleckner7b78d352013-06-26 22:43:37 +000060 }
61 llvm::errs() << ']';
Michael J. Spencer41ee0412012-12-05 00:29:32 +000062 }
Michael J. Spencer41ee0412012-12-05 00:29:32 +000063
64 llvm::errs() << " Name:\"" << getName() << '"';
65
66 const Option Group = getGroup();
67 if (Group.isValid()) {
68 llvm::errs() << " Group:";
69 Group.dump();
70 }
71
72 const Option Alias = getAlias();
73 if (Alias.isValid()) {
74 llvm::errs() << " Alias:";
75 Alias.dump();
76 }
77
78 if (getKind() == MultiArgClass)
79 llvm::errs() << " NumArgs:" << getNumArgs();
80
81 llvm::errs() << ">\n";
82}
83
84bool Option::matches(OptSpecifier Opt) const {
85 // Aliases are never considered in matching, look through them.
86 const Option Alias = getAlias();
87 if (Alias.isValid())
88 return Alias.matches(Opt);
89
90 // Check exact match.
91 if (getID() == Opt.getID())
92 return true;
93
94 const Option Group = getGroup();
95 if (Group.isValid())
96 return Group.matches(Opt);
97 return false;
98}
99
100Arg *Option::accept(const ArgList &Args,
101 unsigned &Index,
102 unsigned ArgSize) const {
103 const Option &UnaliasedOption = getUnaliasedOption();
104 StringRef Spelling;
105 // If the option was an alias, get the spelling from the unaliased one.
106 if (getID() == UnaliasedOption.getID()) {
107 Spelling = StringRef(Args.getArgString(Index), ArgSize);
108 } else {
109 Spelling = Args.MakeArgString(Twine(UnaliasedOption.getPrefix()) +
110 Twine(UnaliasedOption.getName()));
111 }
112
113 switch (getKind()) {
Hans Wennborg5fdcf862013-07-31 22:44:41 +0000114 case FlagClass: {
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000115 if (ArgSize != strlen(Args.getArgString(Index)))
Craig Topper2617dcc2014-04-15 06:32:26 +0000116 return nullptr;
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000117
Hans Wennborg5fdcf862013-07-31 22:44:41 +0000118 Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
119 if (getAliasArgs()) {
120 const char *Val = getAliasArgs();
121 while (*Val != '\0') {
122 A->getValues().push_back(Val);
123
124 // Move past the '\0' to the next argument.
125 Val += strlen(Val) + 1;
126 }
127 }
Hans Wennborg8d8146f2015-05-04 18:00:13 +0000128
129 if (UnaliasedOption.getKind() == JoinedClass && !getAliasArgs())
130 // A Flag alias for a Joined option must provide an argument.
131 A->getValues().push_back("");
132
Hans Wennborg5fdcf862013-07-31 22:44:41 +0000133 return A;
134 }
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000135 case JoinedClass: {
136 const char *Value = Args.getArgString(Index) + ArgSize;
137 return new Arg(UnaliasedOption, Spelling, Index++, Value);
138 }
139 case CommaJoinedClass: {
140 // Always matches.
141 const char *Str = Args.getArgString(Index) + ArgSize;
142 Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
143
144 // Parse out the comma separated values.
145 const char *Prev = Str;
146 for (;; ++Str) {
147 char c = *Str;
148
149 if (!c || c == ',') {
150 if (Prev != Str) {
151 char *Value = new char[Str - Prev + 1];
152 memcpy(Value, Prev, Str - Prev);
153 Value[Str - Prev] = '\0';
154 A->getValues().push_back(Value);
155 }
156
157 if (!c)
158 break;
159
160 Prev = Str + 1;
161 }
162 }
163 A->setOwnsValues(true);
164
165 return A;
166 }
167 case SeparateClass:
168 // Matches iff this is an exact match.
169 // FIXME: Avoid strlen.
170 if (ArgSize != strlen(Args.getArgString(Index)))
Craig Topper2617dcc2014-04-15 06:32:26 +0000171 return nullptr;
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000172
173 Index += 2;
Reid Klecknere3f146d2014-08-22 19:29:17 +0000174 if (Index > Args.getNumInputArgStrings() ||
175 Args.getArgString(Index - 1) == nullptr)
Craig Topper2617dcc2014-04-15 06:32:26 +0000176 return nullptr;
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000177
178 return new Arg(UnaliasedOption, Spelling,
179 Index - 2, Args.getArgString(Index - 1));
180 case MultiArgClass: {
181 // Matches iff this is an exact match.
182 // FIXME: Avoid strlen.
183 if (ArgSize != strlen(Args.getArgString(Index)))
Craig Topper2617dcc2014-04-15 06:32:26 +0000184 return nullptr;
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000185
186 Index += 1 + getNumArgs();
187 if (Index > Args.getNumInputArgStrings())
Craig Topper2617dcc2014-04-15 06:32:26 +0000188 return nullptr;
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000189
190 Arg *A = new Arg(UnaliasedOption, Spelling, Index - 1 - getNumArgs(),
191 Args.getArgString(Index - getNumArgs()));
192 for (unsigned i = 1; i != getNumArgs(); ++i)
193 A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
194 return A;
195 }
196 case JoinedOrSeparateClass: {
197 // If this is not an exact match, it is a joined arg.
198 // FIXME: Avoid strlen.
199 if (ArgSize != strlen(Args.getArgString(Index))) {
200 const char *Value = Args.getArgString(Index) + ArgSize;
201 return new Arg(*this, Spelling, Index++, Value);
202 }
203
204 // Otherwise it must be separate.
205 Index += 2;
Reid Klecknere3f146d2014-08-22 19:29:17 +0000206 if (Index > Args.getNumInputArgStrings() ||
207 Args.getArgString(Index - 1) == nullptr)
Craig Topper2617dcc2014-04-15 06:32:26 +0000208 return nullptr;
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000209
210 return new Arg(UnaliasedOption, Spelling,
211 Index - 2, Args.getArgString(Index - 1));
212 }
213 case JoinedAndSeparateClass:
214 // Always matches.
215 Index += 2;
Reid Klecknere3f146d2014-08-22 19:29:17 +0000216 if (Index > Args.getNumInputArgStrings() ||
217 Args.getArgString(Index - 1) == nullptr)
Craig Topper2617dcc2014-04-15 06:32:26 +0000218 return nullptr;
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000219
220 return new Arg(UnaliasedOption, Spelling, Index - 2,
221 Args.getArgString(Index - 2) + ArgSize,
222 Args.getArgString(Index - 1));
Hans Wennborgd505fbf2013-08-13 21:09:50 +0000223 case RemainingArgsClass: {
224 // Matches iff this is an exact match.
225 // FIXME: Avoid strlen.
226 if (ArgSize != strlen(Args.getArgString(Index)))
Craig Topper2617dcc2014-04-15 06:32:26 +0000227 return nullptr;
Hans Wennborgd505fbf2013-08-13 21:09:50 +0000228 Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
Reid Klecknere3f146d2014-08-22 19:29:17 +0000229 while (Index < Args.getNumInputArgStrings() &&
230 Args.getArgString(Index) != nullptr)
Hans Wennborgd505fbf2013-08-13 21:09:50 +0000231 A->getValues().push_back(Args.getArgString(Index++));
232 return A;
233 }
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000234 default:
235 llvm_unreachable("Invalid option kind!");
236 }
237}