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