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