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