]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/tools/clang/lib/Driver/Option.cpp
MFC r244628:
[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 "llvm/ADT/Twine.h"
17 #include <cassert>
18 #include <algorithm>
19 using namespace clang::driver;
20
21 Option::Option(const OptTable::Info *info, const OptTable *owner)
22   : Info(info), Owner(owner) {
23
24   // Multi-level aliases are not supported, and alias options cannot
25   // have groups. This just simplifies option tracking, it is not an
26   // inherent limitation.
27   assert((!Info || !getAlias().isValid() || (!getAlias().getAlias().isValid() &&
28          !getGroup().isValid())) &&
29          "Multi-level aliases and aliases with groups are unsupported.");
30 }
31
32 Option::~Option() {
33 }
34
35 void Option::dump() const {
36   llvm::errs() << "<";
37   switch (getKind()) {
38 #define P(N) case N: llvm::errs() << #N; break
39     P(GroupClass);
40     P(InputClass);
41     P(UnknownClass);
42     P(FlagClass);
43     P(JoinedClass);
44     P(SeparateClass);
45     P(CommaJoinedClass);
46     P(MultiArgClass);
47     P(JoinedOrSeparateClass);
48     P(JoinedAndSeparateClass);
49 #undef P
50   }
51
52   llvm::errs() << " Prefixes:[";
53   for (const char * const *Pre = Info->Prefixes; *Pre != 0; ++Pre) {
54     llvm::errs() << '"' << *Pre << (*(Pre + 1) == 0 ? "\"" : "\", ");
55   }
56   llvm::errs() << ']';
57
58   llvm::errs() << " Name:\"" << getName() << '"';
59
60   const Option Group = getGroup();
61   if (Group.isValid()) {
62     llvm::errs() << " Group:";
63     Group.dump();
64   }
65
66   const Option Alias = getAlias();
67   if (Alias.isValid()) {
68     llvm::errs() << " Alias:";
69     Alias.dump();
70   }
71
72   if (getKind() == MultiArgClass)
73     llvm::errs() << " NumArgs:" << getNumArgs();
74
75   llvm::errs() << ">\n";
76 }
77
78 bool Option::matches(OptSpecifier Opt) const {
79   // Aliases are never considered in matching, look through them.
80   const Option Alias = getAlias();
81   if (Alias.isValid())
82     return Alias.matches(Opt);
83
84   // Check exact match.
85   if (getID() == Opt.getID())
86     return true;
87
88   const Option Group = getGroup();
89   if (Group.isValid())
90     return Group.matches(Opt);
91   return false;
92 }
93
94 Arg *Option::accept(const ArgList &Args,
95                     unsigned &Index,
96                     unsigned ArgSize) const {
97   const Option &UnaliasedOption = getUnaliasedOption();
98   StringRef Spelling;
99   // If the option was an alias, get the spelling from the unaliased one.
100   if (getID() == UnaliasedOption.getID()) {
101     Spelling = StringRef(Args.getArgString(Index), ArgSize);
102   } else {
103     Spelling = Args.MakeArgString(Twine(UnaliasedOption.getPrefix()) +
104                                   Twine(UnaliasedOption.getName()));
105   }
106
107   switch (getKind()) {
108   case FlagClass:
109     if (ArgSize != strlen(Args.getArgString(Index)))
110       return 0;
111
112     return new Arg(UnaliasedOption, Spelling, Index++);
113   case JoinedClass: {
114     const char *Value = Args.getArgString(Index) + ArgSize;
115     return new Arg(UnaliasedOption, Spelling, Index++, Value);
116   }
117   case CommaJoinedClass: {
118     // Always matches.
119     const char *Str = Args.getArgString(Index) + ArgSize;
120     Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
121
122     // Parse out the comma separated values.
123     const char *Prev = Str;
124     for (;; ++Str) {
125       char c = *Str;
126
127       if (!c || c == ',') {
128         if (Prev != Str) {
129           char *Value = new char[Str - Prev + 1];
130           memcpy(Value, Prev, Str - Prev);
131           Value[Str - Prev] = '\0';
132           A->getValues().push_back(Value);
133         }
134
135         if (!c)
136           break;
137
138         Prev = Str + 1;
139       }
140     }
141     A->setOwnsValues(true);
142
143     return A;
144   }
145   case SeparateClass:
146     // Matches iff this is an exact match.
147     // FIXME: Avoid strlen.
148     if (ArgSize != strlen(Args.getArgString(Index)))
149       return 0;
150
151     Index += 2;
152     if (Index > Args.getNumInputArgStrings())
153       return 0;
154
155     return new Arg(UnaliasedOption, Spelling,
156                    Index - 2, Args.getArgString(Index - 1));
157   case MultiArgClass: {
158     // Matches iff this is an exact match.
159     // FIXME: Avoid strlen.
160     if (ArgSize != strlen(Args.getArgString(Index)))
161       return 0;
162
163     Index += 1 + getNumArgs();
164     if (Index > Args.getNumInputArgStrings())
165       return 0;
166
167     Arg *A = new Arg(UnaliasedOption, Spelling, Index - 1 - getNumArgs(),
168                       Args.getArgString(Index - getNumArgs()));
169     for (unsigned i = 1; i != getNumArgs(); ++i)
170       A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
171     return A;
172   }
173   case JoinedOrSeparateClass: {
174     // If this is not an exact match, it is a joined arg.
175     // FIXME: Avoid strlen.
176     if (ArgSize != strlen(Args.getArgString(Index))) {
177       const char *Value = Args.getArgString(Index) + ArgSize;
178       return new Arg(*this, Spelling, Index++, Value);
179     }
180
181     // Otherwise it must be separate.
182     Index += 2;
183     if (Index > Args.getNumInputArgStrings())
184       return 0;
185
186     return new Arg(UnaliasedOption, Spelling,
187                    Index - 2, Args.getArgString(Index - 1));
188   }
189   case JoinedAndSeparateClass:
190     // Always matches.
191     Index += 2;
192     if (Index > Args.getNumInputArgStrings())
193       return 0;
194
195     return new Arg(UnaliasedOption, Spelling, Index - 2,
196                    Args.getArgString(Index - 2) + ArgSize,
197                    Args.getArgString(Index - 1));
198   default:
199     llvm_unreachable("Invalid option kind!");
200   }
201 }