blob: dbc61ea3a4f72186707c1d21fe18a184f74e457a [file] [log] [blame]
Nick Lewycky3fdcc6f2010-12-31 17:31:54 +00001//===--- Option.cpp - Abstract Driver Options -----------------------------===//
Daniel Dunbar1eb4e642009-03-03 05:55:11 +00002//
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"
Daniel Dunbarbbf842b2009-03-04 23:22:02 +000011#include "clang/Driver/Arg.h"
12#include "clang/Driver/ArgList.h"
Argyrios Kyrtzidisa049bbb2012-10-26 19:36:33 +000013#include "llvm/ADT/Twine.h"
Chandler Carruth55fc8732012-12-04 09:13:33 +000014#include "llvm/Support/ErrorHandling.h"
15#include "llvm/Support/raw_ostream.h"
Daniel Dunbarbbf842b2009-03-04 23:22:02 +000016#include <algorithm>
Chandler Carruth55fc8732012-12-04 09:13:33 +000017#include <cassert>
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000018using namespace clang::driver;
19
Michael J. Spencer9b7dcdb2012-10-03 19:58:10 +000020Option::Option(const OptTable::Info *info, const OptTable *owner)
21 : Info(info), Owner(owner) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000022
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.
Benjamin Kramer6592c772012-10-21 15:21:56 +000026 assert((!Info || !getAlias().isValid() || (!getAlias().getAlias().isValid() &&
Michael J. Spencere4151c52012-10-19 22:36:40 +000027 !getGroup().isValid())) &&
Mike Stump1eb44332009-09-09 15:08:12 +000028 "Multi-level aliases and aliases with groups are unsupported.");
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000029}
30
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000031Option::~Option() {
32}
33
34void Option::dump() const {
35 llvm::errs() << "<";
Michael J. Spencer04a42792012-08-21 18:51:17 +000036 switch (getKind()) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000037#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
Michael J. Spencerc6357102012-10-22 22:13:48 +000051 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
Michael J. Spencer04a42792012-08-21 18:51:17 +000057 llvm::errs() << " Name:\"" << getName() << '"';
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000058
Michael J. Spencere4151c52012-10-19 22:36:40 +000059 const Option Group = getGroup();
60 if (Group.isValid()) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000061 llvm::errs() << " Group:";
Michael J. Spencere4151c52012-10-19 22:36:40 +000062 Group.dump();
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000063 }
Mike Stump1eb44332009-09-09 15:08:12 +000064
Michael J. Spencere4151c52012-10-19 22:36:40 +000065 const Option Alias = getAlias();
66 if (Alias.isValid()) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000067 llvm::errs() << " Alias:";
Michael J. Spencere4151c52012-10-19 22:36:40 +000068 Alias.dump();
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000069 }
Mike Stump1eb44332009-09-09 15:08:12 +000070
Michael J. Spencer04a42792012-08-21 18:51:17 +000071 if (getKind() == MultiArgClass)
72 llvm::errs() << " NumArgs:" << getNumArgs();
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000073
74 llvm::errs() << ">\n";
75}
76
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000077bool Option::matches(OptSpecifier Opt) const {
Daniel Dunbarb32aa512009-11-19 03:26:50 +000078 // Aliases are never considered in matching, look through them.
Michael J. Spencere4151c52012-10-19 22:36:40 +000079 const Option Alias = getAlias();
80 if (Alias.isValid())
81 return Alias.matches(Opt);
Mike Stump1eb44332009-09-09 15:08:12 +000082
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000083 // Check exact match.
Michael J. Spencer663117a2012-09-25 23:12:48 +000084 if (getID() == Opt.getID())
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000085 return true;
Mike Stump1eb44332009-09-09 15:08:12 +000086
Michael J. Spencere4151c52012-10-19 22:36:40 +000087 const Option Group = getGroup();
88 if (Group.isValid())
89 return Group.matches(Opt);
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000090 return false;
91}
92
Michael J. Spencerc6357102012-10-22 22:13:48 +000093Arg *Option::accept(const ArgList &Args,
94 unsigned &Index,
95 unsigned ArgSize) const {
Argyrios Kyrtzidisa049bbb2012-10-26 19:36:33 +000096 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
Michael J. Spencer04a42792012-08-21 18:51:17 +0000106 switch (getKind()) {
Michael J. Spencer43275572012-08-20 21:41:17 +0000107 case FlagClass:
Michael J. Spencerc6357102012-10-22 22:13:48 +0000108 if (ArgSize != strlen(Args.getArgString(Index)))
Michael J. Spencer43275572012-08-20 21:41:17 +0000109 return 0;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000110
Argyrios Kyrtzidisa049bbb2012-10-26 19:36:33 +0000111 return new Arg(UnaliasedOption, Spelling, Index++);
Michael J. Spencer43275572012-08-20 21:41:17 +0000112 case JoinedClass: {
Michael J. Spencerc6357102012-10-22 22:13:48 +0000113 const char *Value = Args.getArgString(Index) + ArgSize;
Argyrios Kyrtzidisa049bbb2012-10-26 19:36:33 +0000114 return new Arg(UnaliasedOption, Spelling, Index++, Value);
Daniel Dunbar4465a772010-06-09 22:31:00 +0000115 }
Michael J. Spencer43275572012-08-20 21:41:17 +0000116 case CommaJoinedClass: {
117 // Always matches.
Michael J. Spencerc6357102012-10-22 22:13:48 +0000118 const char *Str = Args.getArgString(Index) + ArgSize;
Argyrios Kyrtzidisa049bbb2012-10-26 19:36:33 +0000119 Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000120
Michael J. Spencer43275572012-08-20 21:41:17 +0000121 // Parse out the comma separated values.
122 const char *Prev = Str;
123 for (;; ++Str) {
124 char c = *Str;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000125
Michael J. Spencer43275572012-08-20 21:41:17 +0000126 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 }
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000133
Michael J. Spencer43275572012-08-20 21:41:17 +0000134 if (!c)
135 break;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000136
Michael J. Spencer43275572012-08-20 21:41:17 +0000137 Prev = Str + 1;
138 }
139 }
140 A->setOwnsValues(true);
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000141
Michael J. Spencer43275572012-08-20 21:41:17 +0000142 return A;
143 }
144 case SeparateClass:
Sylvestre Ledruf3477c12012-09-27 10:16:10 +0000145 // Matches iff this is an exact match.
Michael J. Spencer43275572012-08-20 21:41:17 +0000146 // FIXME: Avoid strlen.
Michael J. Spencerc6357102012-10-22 22:13:48 +0000147 if (ArgSize != strlen(Args.getArgString(Index)))
Michael J. Spencer43275572012-08-20 21:41:17 +0000148 return 0;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000149
Michael J. Spencer43275572012-08-20 21:41:17 +0000150 Index += 2;
151 if (Index > Args.getNumInputArgStrings())
152 return 0;
153
Argyrios Kyrtzidisa049bbb2012-10-26 19:36:33 +0000154 return new Arg(UnaliasedOption, Spelling,
Michael J. Spencer43275572012-08-20 21:41:17 +0000155 Index - 2, Args.getArgString(Index - 1));
156 case MultiArgClass: {
Sylvestre Ledruf3477c12012-09-27 10:16:10 +0000157 // Matches iff this is an exact match.
Michael J. Spencer43275572012-08-20 21:41:17 +0000158 // FIXME: Avoid strlen.
Michael J. Spencerc6357102012-10-22 22:13:48 +0000159 if (ArgSize != strlen(Args.getArgString(Index)))
Michael J. Spencer43275572012-08-20 21:41:17 +0000160 return 0;
161
Michael J. Spencer04a42792012-08-21 18:51:17 +0000162 Index += 1 + getNumArgs();
Michael J. Spencer43275572012-08-20 21:41:17 +0000163 if (Index > Args.getNumInputArgStrings())
164 return 0;
165
Argyrios Kyrtzidisa049bbb2012-10-26 19:36:33 +0000166 Arg *A = new Arg(UnaliasedOption, Spelling, Index - 1 - getNumArgs(),
Michael J. Spencer04a42792012-08-21 18:51:17 +0000167 Args.getArgString(Index - getNumArgs()));
168 for (unsigned i = 1; i != getNumArgs(); ++i)
169 A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
Michael J. Spencer43275572012-08-20 21:41:17 +0000170 return A;
171 }
172 case JoinedOrSeparateClass: {
173 // If this is not an exact match, it is a joined arg.
174 // FIXME: Avoid strlen.
Michael J. Spencerc6357102012-10-22 22:13:48 +0000175 if (ArgSize != strlen(Args.getArgString(Index))) {
176 const char *Value = Args.getArgString(Index) + ArgSize;
177 return new Arg(*this, Spelling, Index++, Value);
Michael J. Spencer43275572012-08-20 21:41:17 +0000178 }
179
180 // Otherwise it must be separate.
181 Index += 2;
182 if (Index > Args.getNumInputArgStrings())
183 return 0;
184
Argyrios Kyrtzidisa049bbb2012-10-26 19:36:33 +0000185 return new Arg(UnaliasedOption, Spelling,
Michael J. Spencer43275572012-08-20 21:41:17 +0000186 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
Argyrios Kyrtzidisa049bbb2012-10-26 19:36:33 +0000194 return new Arg(UnaliasedOption, Spelling, Index - 2,
Michael J. Spencerc6357102012-10-22 22:13:48 +0000195 Args.getArgString(Index - 2) + ArgSize,
196 Args.getArgString(Index - 1));
David Blaikie279e0be2012-08-20 22:22:51 +0000197 default:
198 llvm_unreachable("Invalid option kind!");
Michael J. Spencer43275572012-08-20 21:41:17 +0000199 }
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000200}