]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/llvm/tools/clang/lib/Driver/Option.cpp
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.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   default:
65     llvm_unreachable("Invalid kind");
66 #define P(N) case N: llvm::errs() << #N; break
67     P(GroupClass);
68     P(InputClass);
69     P(UnknownClass);
70     P(FlagClass);
71     P(JoinedClass);
72     P(SeparateClass);
73     P(CommaJoinedClass);
74     P(MultiArgClass);
75     P(JoinedOrSeparateClass);
76     P(JoinedAndSeparateClass);
77 #undef P
78   }
79
80   llvm::errs() << " Name:\"" << Name << '"';
81
82   if (Group) {
83     llvm::errs() << " Group:";
84     Group->dump();
85   }
86
87   if (Alias) {
88     llvm::errs() << " Alias:";
89     Alias->dump();
90   }
91
92   if (const MultiArgOption *MOA = dyn_cast<MultiArgOption>(this))
93     llvm::errs() << " NumArgs:" << MOA->getNumArgs();
94
95   llvm::errs() << ">\n";
96 }
97
98 bool Option::matches(OptSpecifier Opt) const {
99   // Aliases are never considered in matching, look through them.
100   if (Alias)
101     return Alias->matches(Opt);
102
103   // Check exact match.
104   if (ID == Opt)
105     return true;
106
107   if (Group)
108     return Group->matches(Opt);
109   return false;
110 }
111
112 OptionGroup::OptionGroup(OptSpecifier ID, const char *Name,
113                          const OptionGroup *Group)
114   : Option(Option::GroupClass, ID, Name, Group, 0) {
115 }
116
117 Arg *OptionGroup::accept(const ArgList &Args, unsigned &Index) const {
118   llvm_unreachable("accept() should never be called on an OptionGroup");
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   llvm_unreachable("accept() should never be called on an InputOption");
127 }
128
129 UnknownOption::UnknownOption(OptSpecifier ID)
130   : Option(Option::UnknownClass, ID, "<unknown>", 0, 0) {
131 }
132
133 Arg *UnknownOption::accept(const ArgList &Args, unsigned &Index) const {
134   llvm_unreachable("accept() should never be called on an UnknownOption");
135 }
136
137 FlagOption::FlagOption(OptSpecifier ID, const char *Name,
138                        const OptionGroup *Group, const Option *Alias)
139   : Option(Option::FlagClass, ID, Name, Group, Alias) {
140 }
141
142 Arg *FlagOption::accept(const ArgList &Args, unsigned &Index) const {
143   // Matches iff this is an exact match.
144   // FIXME: Avoid strlen.
145   if (getName().size() != strlen(Args.getArgString(Index)))
146     return 0;
147
148   return new Arg(getUnaliasedOption(), Index++);
149 }
150
151 JoinedOption::JoinedOption(OptSpecifier ID, const char *Name,
152                            const OptionGroup *Group, const Option *Alias)
153   : Option(Option::JoinedClass, ID, Name, Group, Alias) {
154 }
155
156 Arg *JoinedOption::accept(const ArgList &Args, unsigned &Index) const {
157   // Always matches.
158   const char *Value = Args.getArgString(Index) + getName().size();
159   return new Arg(getUnaliasedOption(), Index++, Value);
160 }
161
162 CommaJoinedOption::CommaJoinedOption(OptSpecifier ID, const char *Name,
163                                      const OptionGroup *Group,
164                                      const Option *Alias)
165   : Option(Option::CommaJoinedClass, ID, Name, Group, Alias) {
166 }
167
168 Arg *CommaJoinedOption::accept(const ArgList &Args,
169                                unsigned &Index) const {
170   // Always matches.
171   const char *Str = Args.getArgString(Index) + getName().size();
172   Arg *A = new Arg(getUnaliasedOption(), Index++);
173
174   // Parse out the comma separated values.
175   const char *Prev = Str;
176   for (;; ++Str) {
177     char c = *Str;
178
179     if (!c || c == ',') {
180       if (Prev != Str) {
181         char *Value = new char[Str - Prev + 1];
182         memcpy(Value, Prev, Str - Prev);
183         Value[Str - Prev] = '\0';
184         A->getValues().push_back(Value);
185       }
186
187       if (!c)
188         break;
189
190       Prev = Str + 1;
191     }
192   }
193   A->setOwnsValues(true);
194
195   return A;
196 }
197
198 SeparateOption::SeparateOption(OptSpecifier ID, const char *Name,
199                                const OptionGroup *Group, const Option *Alias)
200   : Option(Option::SeparateClass, ID, Name, Group, Alias) {
201 }
202
203 Arg *SeparateOption::accept(const ArgList &Args, unsigned &Index) const {
204   // Matches iff this is an exact match.
205   // FIXME: Avoid strlen.
206   if (getName().size() != strlen(Args.getArgString(Index)))
207     return 0;
208
209   Index += 2;
210   if (Index > Args.getNumInputArgStrings())
211     return 0;
212
213   return new Arg(getUnaliasedOption(), Index - 2, Args.getArgString(Index - 1));
214 }
215
216 MultiArgOption::MultiArgOption(OptSpecifier ID, const char *Name,
217                                const OptionGroup *Group, const Option *Alias,
218                                unsigned _NumArgs)
219   : Option(Option::MultiArgClass, ID, Name, Group, Alias), NumArgs(_NumArgs) {
220   assert(NumArgs > 1  && "Invalid MultiArgOption!");
221 }
222
223 Arg *MultiArgOption::accept(const ArgList &Args, unsigned &Index) const {
224   // Matches iff this is an exact match.
225   // FIXME: Avoid strlen.
226   if (getName().size() != strlen(Args.getArgString(Index)))
227     return 0;
228
229   Index += 1 + NumArgs;
230   if (Index > Args.getNumInputArgStrings())
231     return 0;
232
233   Arg *A = new Arg(getUnaliasedOption(), Index - 1 - NumArgs,
234                    Args.getArgString(Index - NumArgs));
235   for (unsigned i = 1; i != NumArgs; ++i)
236     A->getValues().push_back(Args.getArgString(Index - NumArgs + i));
237   return A;
238 }
239
240 JoinedOrSeparateOption::JoinedOrSeparateOption(OptSpecifier ID,
241                                                const char *Name,
242                                                const OptionGroup *Group,
243                                                const Option *Alias)
244   : Option(Option::JoinedOrSeparateClass, ID, Name, Group, Alias) {
245 }
246
247 Arg *JoinedOrSeparateOption::accept(const ArgList &Args,
248                                     unsigned &Index) const {
249   // If this is not an exact match, it is a joined arg.
250   // FIXME: Avoid strlen.
251   if (getName().size() != strlen(Args.getArgString(Index))) {
252     const char *Value = Args.getArgString(Index) + getName().size();
253     return new Arg(this, Index++, Value);
254   }
255
256   // Otherwise it must be separate.
257   Index += 2;
258   if (Index > Args.getNumInputArgStrings())
259     return 0;
260
261   return new Arg(getUnaliasedOption(), Index - 2, Args.getArgString(Index - 1));
262 }
263
264 JoinedAndSeparateOption::JoinedAndSeparateOption(OptSpecifier ID,
265                                                  const char *Name,
266                                                  const OptionGroup *Group,
267                                                  const Option *Alias)
268   : Option(Option::JoinedAndSeparateClass, ID, Name, Group, Alias) {
269 }
270
271 Arg *JoinedAndSeparateOption::accept(const ArgList &Args,
272                                      unsigned &Index) const {
273   // Always matches.
274
275   Index += 2;
276   if (Index > Args.getNumInputArgStrings())
277     return 0;
278
279   return new Arg(getUnaliasedOption(), Index - 2,
280                  Args.getArgString(Index-2)+getName().size(),
281                  Args.getArgString(Index-1));
282 }