• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Option(OptionClass _Kind,OptSpecifier _ID,const char * _Name,const OptionGroup * _Group,const Option * _Alias)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 
~Option()58 Option::~Option() {
59 }
60 
dump() const61 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 
matches(OptSpecifier Opt) const96 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 
OptionGroup(OptSpecifier ID,const char * Name,const OptionGroup * Group)110 OptionGroup::OptionGroup(OptSpecifier ID, const char *Name,
111                          const OptionGroup *Group)
112   : Option(Option::GroupClass, ID, Name, Group, 0) {
113 }
114 
accept(const ArgList & Args,unsigned & Index) const115 Arg *OptionGroup::accept(const ArgList &Args, unsigned &Index) const {
116   llvm_unreachable("accept() should never be called on an OptionGroup");
117 }
118 
InputOption(OptSpecifier ID)119 InputOption::InputOption(OptSpecifier ID)
120   : Option(Option::InputClass, ID, "<input>", 0, 0) {
121 }
122 
accept(const ArgList & Args,unsigned & Index) const123 Arg *InputOption::accept(const ArgList &Args, unsigned &Index) const {
124   llvm_unreachable("accept() should never be called on an InputOption");
125 }
126 
UnknownOption(OptSpecifier ID)127 UnknownOption::UnknownOption(OptSpecifier ID)
128   : Option(Option::UnknownClass, ID, "<unknown>", 0, 0) {
129 }
130 
accept(const ArgList & Args,unsigned & Index) const131 Arg *UnknownOption::accept(const ArgList &Args, unsigned &Index) const {
132   llvm_unreachable("accept() should never be called on an UnknownOption");
133 }
134 
FlagOption(OptSpecifier ID,const char * Name,const OptionGroup * Group,const Option * Alias)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 
accept(const ArgList & Args,unsigned & Index) const140 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 
JoinedOption(OptSpecifier ID,const char * Name,const OptionGroup * Group,const Option * Alias)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 
accept(const ArgList & Args,unsigned & Index) const154 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 
CommaJoinedOption(OptSpecifier ID,const char * Name,const OptionGroup * Group,const Option * Alias)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 
accept(const ArgList & Args,unsigned & Index) const166 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 
SeparateOption(OptSpecifier ID,const char * Name,const OptionGroup * Group,const Option * Alias)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 
accept(const ArgList & Args,unsigned & Index) const201 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 
MultiArgOption(OptSpecifier ID,const char * Name,const OptionGroup * Group,const Option * Alias,unsigned _NumArgs)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 
accept(const ArgList & Args,unsigned & Index) const221 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 
JoinedOrSeparateOption(OptSpecifier ID,const char * Name,const OptionGroup * Group,const Option * Alias)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 
accept(const ArgList & Args,unsigned & Index) const245 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 
JoinedAndSeparateOption(OptSpecifier ID,const char * Name,const OptionGroup * Group,const Option * Alias)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 
accept(const ArgList & Args,unsigned & Index) const269 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 }
281