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