]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/tools/clang/lib/Driver/Option.cpp
MFC r234353:
[FreeBSD/stable/9.git] / contrib / llvm / tools / clang / lib / Driver / Option.cpp
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 "clang/Driver/Option.h"
11
12 #include "clang/Driver/Arg.h"
13 #include "clang/Driver/ArgList.h"
14 #include "llvm/Support/raw_ostream.h"
15 #include "llvm/Support/ErrorHandling.h"
16 #include <cassert>
17 #include <algorithm>
18 using namespace clang::driver;
19
20 Option::Option(OptionClass _Kind, OptSpecifier _ID, const char *_Name,
21                const OptionGroup *_Group, const Option *_Alias)
22   : Kind(_Kind), ID(_ID.getID()), Name(_Name), Group(_Group), Alias(_Alias),
23     Unsupported(false), LinkerInput(false), NoOptAsInput(false),
24     DriverOption(false), NoArgumentUnused(false), NoForward(false) {
25
26   // Multi-level aliases are not supported, and alias options cannot
27   // have groups. This just simplifies option tracking, it is not an
28   // inherent limitation.
29   assert((!Alias || (!Alias->Alias && !Group)) &&
30          "Multi-level aliases and aliases with groups are unsupported.");
31
32   // Initialize rendering options based on the class.
33   switch (Kind) {
34   case GroupClass:
35   case InputClass:
36   case UnknownClass:
37     RenderStyle = RenderValuesStyle;
38     break;
39
40   case JoinedClass:
41   case JoinedAndSeparateClass:
42     RenderStyle = RenderJoinedStyle;
43     break;
44
45   case CommaJoinedClass:
46     RenderStyle = RenderCommaJoinedStyle;
47     break;
48
49   case FlagClass:
50   case SeparateClass:
51   case MultiArgClass:
52   case JoinedOrSeparateClass:
53     RenderStyle = RenderSeparateStyle;
54     break;
55   }
56 }
57
58 Option::~Option() {
59 }
60
61 void Option::dump() const {
62   llvm::errs() << "<";
63   switch (Kind) {
64 #define P(N) case N: llvm::errs() << #N; break
65     P(GroupClass);
66     P(InputClass);
67     P(UnknownClass);
68     P(FlagClass);
69     P(JoinedClass);
70     P(SeparateClass);
71     P(CommaJoinedClass);
72     P(MultiArgClass);
73     P(JoinedOrSeparateClass);
74     P(JoinedAndSeparateClass);
75 #undef P
76   }
77
78   llvm::errs() << " Name:\"" << Name << '"';
79
80   if (Group) {
81     llvm::errs() << " Group:";
82     Group->dump();
83   }
84
85   if (Alias) {
86     llvm::errs() << " Alias:";
87     Alias->dump();
88   }
89
90   if (const MultiArgOption *MOA = dyn_cast<MultiArgOption>(this))
91     llvm::errs() << " NumArgs:" << MOA->getNumArgs();
92
93   llvm::errs() << ">\n";
94 }
95
96 bool Option::matches(OptSpecifier Opt) const {
97   // Aliases are never considered in matching, look through them.
98   if (Alias)
99     return Alias->matches(Opt);
100
101   // Check exact match.
102   if (ID == Opt)
103     return true;
104
105   if (Group)
106     return Group->matches(Opt);
107   return false;
108 }
109
110 OptionGroup::OptionGroup(OptSpecifier ID, const char *Name,
111                          const OptionGroup *Group)
112   : Option(Option::GroupClass, ID, Name, Group, 0) {
113 }
114
115 Arg *OptionGroup::accept(const ArgList &Args, unsigned &Index) const {
116   llvm_unreachable("accept() should never be called on an OptionGroup");
117 }
118
119 InputOption::InputOption(OptSpecifier ID)
120   : Option(Option::InputClass, ID, "<input>", 0, 0) {
121 }
122
123 Arg *InputOption::accept(const ArgList &Args, unsigned &Index) const {
124   llvm_unreachable("accept() should never be called on an InputOption");
125 }
126
127 UnknownOption::UnknownOption(OptSpecifier ID)
128   : Option(Option::UnknownClass, ID, "<unknown>", 0, 0) {
129 }
130
131 Arg *UnknownOption::accept(const ArgList &Args, unsigned &Index) const {
132   llvm_unreachable("accept() should never be called on an UnknownOption");
133 }
134
135 FlagOption::FlagOption(OptSpecifier ID, const char *Name,
136                        const OptionGroup *Group, const Option *Alias)
137   : Option(Option::FlagClass, ID, Name, Group, Alias) {
138 }
139
140 Arg *FlagOption::accept(const ArgList &Args, unsigned &Index) const {
141   // Matches iff this is an exact match.
142   // FIXME: Avoid strlen.
143   if (getName().size() != strlen(Args.getArgString(Index)))
144     return 0;
145
146   return new Arg(getUnaliasedOption(), Index++);
147 }
148
149 JoinedOption::JoinedOption(OptSpecifier ID, const char *Name,
150                            const OptionGroup *Group, const Option *Alias)
151   : Option(Option::JoinedClass, ID, Name, Group, Alias) {
152 }
153
154 Arg *JoinedOption::accept(const ArgList &Args, unsigned &Index) const {
155   // Always matches.
156   const char *Value = Args.getArgString(Index) + getName().size();
157   return new Arg(getUnaliasedOption(), Index++, Value);
158 }
159
160 CommaJoinedOption::CommaJoinedOption(OptSpecifier ID, const char *Name,
161                                      const OptionGroup *Group,
162                                      const Option *Alias)
163   : Option(Option::CommaJoinedClass, ID, Name, Group, Alias) {
164 }
165
166 Arg *CommaJoinedOption::accept(const ArgList &Args,
167                                unsigned &Index) const {
168   // Always matches.
169   const char *Str = Args.getArgString(Index) + getName().size();
170   Arg *A = new Arg(getUnaliasedOption(), Index++);
171
172   // Parse out the comma separated values.
173   const char *Prev = Str;
174   for (;; ++Str) {
175     char c = *Str;
176
177     if (!c || c == ',') {
178       if (Prev != Str) {
179         char *Value = new char[Str - Prev + 1];
180         memcpy(Value, Prev, Str - Prev);
181         Value[Str - Prev] = '\0';
182         A->getValues().push_back(Value);
183       }
184
185       if (!c)
186         break;
187
188       Prev = Str + 1;
189     }
190   }
191   A->setOwnsValues(true);
192
193   return A;
194 }
195
196 SeparateOption::SeparateOption(OptSpecifier ID, const char *Name,
197                                const OptionGroup *Group, const Option *Alias)
198   : Option(Option::SeparateClass, ID, Name, Group, Alias) {
199 }
200
201 Arg *SeparateOption::accept(const ArgList &Args, unsigned &Index) const {
202   // Matches iff this is an exact match.
203   // FIXME: Avoid strlen.
204   if (getName().size() != strlen(Args.getArgString(Index)))
205     return 0;
206
207   Index += 2;
208   if (Index > Args.getNumInputArgStrings())
209     return 0;
210
211   return new Arg(getUnaliasedOption(), Index - 2, Args.getArgString(Index - 1));
212 }
213
214 MultiArgOption::MultiArgOption(OptSpecifier ID, const char *Name,
215                                const OptionGroup *Group, const Option *Alias,
216                                unsigned _NumArgs)
217   : Option(Option::MultiArgClass, ID, Name, Group, Alias), NumArgs(_NumArgs) {
218   assert(NumArgs > 1  && "Invalid MultiArgOption!");
219 }
220
221 Arg *MultiArgOption::accept(const ArgList &Args, unsigned &Index) const {
222   // Matches iff this is an exact match.
223   // FIXME: Avoid strlen.
224   if (getName().size() != strlen(Args.getArgString(Index)))
225     return 0;
226
227   Index += 1 + NumArgs;
228   if (Index > Args.getNumInputArgStrings())
229     return 0;
230
231   Arg *A = new Arg(getUnaliasedOption(), Index - 1 - NumArgs,
232                    Args.getArgString(Index - NumArgs));
233   for (unsigned i = 1; i != NumArgs; ++i)
234     A->getValues().push_back(Args.getArgString(Index - NumArgs + i));
235   return A;
236 }
237
238 JoinedOrSeparateOption::JoinedOrSeparateOption(OptSpecifier ID,
239                                                const char *Name,
240                                                const OptionGroup *Group,
241                                                const Option *Alias)
242   : Option(Option::JoinedOrSeparateClass, ID, Name, Group, Alias) {
243 }
244
245 Arg *JoinedOrSeparateOption::accept(const ArgList &Args,
246                                     unsigned &Index) const {
247   // If this is not an exact match, it is a joined arg.
248   // FIXME: Avoid strlen.
249   if (getName().size() != strlen(Args.getArgString(Index))) {
250     const char *Value = Args.getArgString(Index) + getName().size();
251     return new Arg(this, Index++, Value);
252   }
253
254   // Otherwise it must be separate.
255   Index += 2;
256   if (Index > Args.getNumInputArgStrings())
257     return 0;
258
259   return new Arg(getUnaliasedOption(), Index - 2, Args.getArgString(Index - 1));
260 }
261
262 JoinedAndSeparateOption::JoinedAndSeparateOption(OptSpecifier ID,
263                                                  const char *Name,
264                                                  const OptionGroup *Group,
265                                                  const Option *Alias)
266   : Option(Option::JoinedAndSeparateClass, ID, Name, Group, Alias) {
267 }
268
269 Arg *JoinedAndSeparateOption::accept(const ArgList &Args,
270                                      unsigned &Index) const {
271   // Always matches.
272
273   Index += 2;
274   if (Index > Args.getNumInputArgStrings())
275     return 0;
276
277   return new Arg(getUnaliasedOption(), Index - 2,
278                  Args.getArgString(Index-2)+getName().size(),
279                  Args.getArgString(Index-1));
280 }