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(const OptTable::Info * info,OptSpecifier _ID,const Option * _Group,const Option * _Alias)20 Option::Option(const OptTable::Info *info, OptSpecifier _ID,
21 const Option *_Group, const Option *_Alias)
22 : Info(info), ID(_ID.getID()), Group(_Group), Alias(_Alias) {
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((!Alias || (!Alias->Alias && !Group)) &&
28 "Multi-level aliases and aliases with groups are unsupported.");
29 }
30
~Option()31 Option::~Option() {
32 }
33
dump() const34 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() << " Name:\"" << getName() << '"';
52
53 if (Group) {
54 llvm::errs() << " Group:";
55 Group->dump();
56 }
57
58 if (Alias) {
59 llvm::errs() << " Alias:";
60 Alias->dump();
61 }
62
63 if (getKind() == MultiArgClass)
64 llvm::errs() << " NumArgs:" << getNumArgs();
65
66 llvm::errs() << ">\n";
67 }
68
matches(OptSpecifier Opt) const69 bool Option::matches(OptSpecifier Opt) const {
70 // Aliases are never considered in matching, look through them.
71 if (Alias)
72 return Alias->matches(Opt);
73
74 // Check exact match.
75 if (ID == Opt)
76 return true;
77
78 if (Group)
79 return Group->matches(Opt);
80 return false;
81 }
82
accept(const ArgList & Args,unsigned & Index) const83 Arg *Option::accept(const ArgList &Args, unsigned &Index) const {
84 switch (getKind()) {
85 case FlagClass:
86 if (getName().size() != strlen(Args.getArgString(Index)))
87 return 0;
88
89 return new Arg(getUnaliasedOption(), Index++);
90 case JoinedClass: {
91 const char *Value = Args.getArgString(Index) + getName().size();
92 return new Arg(getUnaliasedOption(), Index++, Value);
93 }
94 case CommaJoinedClass: {
95 // Always matches.
96 const char *Str = Args.getArgString(Index) + getName().size();
97 Arg *A = new Arg(getUnaliasedOption(), Index++);
98
99 // Parse out the comma separated values.
100 const char *Prev = Str;
101 for (;; ++Str) {
102 char c = *Str;
103
104 if (!c || c == ',') {
105 if (Prev != Str) {
106 char *Value = new char[Str - Prev + 1];
107 memcpy(Value, Prev, Str - Prev);
108 Value[Str - Prev] = '\0';
109 A->getValues().push_back(Value);
110 }
111
112 if (!c)
113 break;
114
115 Prev = Str + 1;
116 }
117 }
118 A->setOwnsValues(true);
119
120 return A;
121 }
122 case SeparateClass:
123 // Matches iff this is an exact match.
124 // FIXME: Avoid strlen.
125 if (getName().size() != strlen(Args.getArgString(Index)))
126 return 0;
127
128 Index += 2;
129 if (Index > Args.getNumInputArgStrings())
130 return 0;
131
132 return new Arg(getUnaliasedOption(),
133 Index - 2, Args.getArgString(Index - 1));
134 case MultiArgClass: {
135 // Matches iff this is an exact match.
136 // FIXME: Avoid strlen.
137 if (getName().size() != strlen(Args.getArgString(Index)))
138 return 0;
139
140 Index += 1 + getNumArgs();
141 if (Index > Args.getNumInputArgStrings())
142 return 0;
143
144 Arg *A = new Arg(getUnaliasedOption(), Index - 1 - getNumArgs(),
145 Args.getArgString(Index - getNumArgs()));
146 for (unsigned i = 1; i != getNumArgs(); ++i)
147 A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
148 return A;
149 }
150 case JoinedOrSeparateClass: {
151 // If this is not an exact match, it is a joined arg.
152 // FIXME: Avoid strlen.
153 if (getName().size() != strlen(Args.getArgString(Index))) {
154 const char *Value = Args.getArgString(Index) + getName().size();
155 return new Arg(this, Index++, Value);
156 }
157
158 // Otherwise it must be separate.
159 Index += 2;
160 if (Index > Args.getNumInputArgStrings())
161 return 0;
162
163 return new Arg(getUnaliasedOption(),
164 Index - 2, Args.getArgString(Index - 1));
165 }
166 case JoinedAndSeparateClass:
167 // Always matches.
168 Index += 2;
169 if (Index > Args.getNumInputArgStrings())
170 return 0;
171
172 return new Arg(getUnaliasedOption(), Index - 2,
173 Args.getArgString(Index-2)+getName().size(),
174 Args.getArgString(Index-1));
175 default:
176 llvm_unreachable("Invalid option kind!");
177 }
178 }
179