blob: 117021b880ce4a5071321e94041024ad6244b90a [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
12#include "clang/Driver/Arg.h"
13#include "clang/Driver/ArgList.h"
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000014#include "llvm/Support/raw_ostream.h"
David Blaikie548f6c82011-09-23 05:57:42 +000015#include "llvm/Support/ErrorHandling.h"
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000016#include <cassert>
Daniel Dunbarbbf842b2009-03-04 23:22:02 +000017#include <algorithm>
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.
Michael J. Spencer9b7dcdb2012-10-03 19:58:10 +000026 assert((!getAlias() || (!getAlias()->getAlias() && !getGroup())) &&
Mike Stump1eb44332009-09-09 15:08:12 +000027 "Multi-level aliases and aliases with groups are unsupported.");
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000028}
29
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000030Option::~Option() {
31}
32
33void Option::dump() const {
34 llvm::errs() << "<";
Michael J. Spencer04a42792012-08-21 18:51:17 +000035 switch (getKind()) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000036#define P(N) case N: llvm::errs() << #N; break
37 P(GroupClass);
38 P(InputClass);
39 P(UnknownClass);
40 P(FlagClass);
41 P(JoinedClass);
42 P(SeparateClass);
43 P(CommaJoinedClass);
44 P(MultiArgClass);
45 P(JoinedOrSeparateClass);
46 P(JoinedAndSeparateClass);
47#undef P
48 }
49
Michael J. Spencer04a42792012-08-21 18:51:17 +000050 llvm::errs() << " Name:\"" << getName() << '"';
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000051
Michael J. Spencer9b7dcdb2012-10-03 19:58:10 +000052 const Option *Group = getGroup();
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000053 if (Group) {
54 llvm::errs() << " Group:";
55 Group->dump();
56 }
Mike Stump1eb44332009-09-09 15:08:12 +000057
Michael J. Spencer9b7dcdb2012-10-03 19:58:10 +000058 const Option *Alias = getAlias();
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000059 if (Alias) {
60 llvm::errs() << " Alias:";
61 Alias->dump();
62 }
Mike Stump1eb44332009-09-09 15:08:12 +000063
Michael J. Spencer04a42792012-08-21 18:51:17 +000064 if (getKind() == MultiArgClass)
65 llvm::errs() << " NumArgs:" << getNumArgs();
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000066
67 llvm::errs() << ">\n";
68}
69
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000070bool Option::matches(OptSpecifier Opt) const {
Daniel Dunbarb32aa512009-11-19 03:26:50 +000071 // Aliases are never considered in matching, look through them.
Michael J. Spencer9b7dcdb2012-10-03 19:58:10 +000072 const Option *Alias = getAlias();
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000073 if (Alias)
74 return Alias->matches(Opt);
Mike Stump1eb44332009-09-09 15:08:12 +000075
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000076 // Check exact match.
Michael J. Spencer663117a2012-09-25 23:12:48 +000077 if (getID() == Opt.getID())
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000078 return true;
Mike Stump1eb44332009-09-09 15:08:12 +000079
Michael J. Spencer9b7dcdb2012-10-03 19:58:10 +000080 const Option *Group = getGroup();
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000081 if (Group)
82 return Group->matches(Opt);
83 return false;
84}
85
Michael J. Spencer43275572012-08-20 21:41:17 +000086Arg *Option::accept(const ArgList &Args, unsigned &Index) const {
Michael J. Spencer04a42792012-08-21 18:51:17 +000087 switch (getKind()) {
Michael J. Spencer43275572012-08-20 21:41:17 +000088 case FlagClass:
89 if (getName().size() != strlen(Args.getArgString(Index)))
90 return 0;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000091
Michael J. Spencer43275572012-08-20 21:41:17 +000092 return new Arg(getUnaliasedOption(), Index++);
93 case JoinedClass: {
Douglas Gregorbcf6a802011-07-05 16:56:25 +000094 const char *Value = Args.getArgString(Index) + getName().size();
Michael J. Spencer43275572012-08-20 21:41:17 +000095 return new Arg(getUnaliasedOption(), Index++, Value);
Daniel Dunbar4465a772010-06-09 22:31:00 +000096 }
Michael J. Spencer43275572012-08-20 21:41:17 +000097 case CommaJoinedClass: {
98 // Always matches.
99 const char *Str = Args.getArgString(Index) + getName().size();
100 Arg *A = new Arg(getUnaliasedOption(), Index++);
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000101
Michael J. Spencer43275572012-08-20 21:41:17 +0000102 // Parse out the comma separated values.
103 const char *Prev = Str;
104 for (;; ++Str) {
105 char c = *Str;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000106
Michael J. Spencer43275572012-08-20 21:41:17 +0000107 if (!c || c == ',') {
108 if (Prev != Str) {
109 char *Value = new char[Str - Prev + 1];
110 memcpy(Value, Prev, Str - Prev);
111 Value[Str - Prev] = '\0';
112 A->getValues().push_back(Value);
113 }
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000114
Michael J. Spencer43275572012-08-20 21:41:17 +0000115 if (!c)
116 break;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000117
Michael J. Spencer43275572012-08-20 21:41:17 +0000118 Prev = Str + 1;
119 }
120 }
121 A->setOwnsValues(true);
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000122
Michael J. Spencer43275572012-08-20 21:41:17 +0000123 return A;
124 }
125 case SeparateClass:
Sylvestre Ledruf3477c12012-09-27 10:16:10 +0000126 // Matches iff this is an exact match.
Michael J. Spencer43275572012-08-20 21:41:17 +0000127 // FIXME: Avoid strlen.
128 if (getName().size() != strlen(Args.getArgString(Index)))
129 return 0;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000130
Michael J. Spencer43275572012-08-20 21:41:17 +0000131 Index += 2;
132 if (Index > Args.getNumInputArgStrings())
133 return 0;
134
135 return new Arg(getUnaliasedOption(),
136 Index - 2, Args.getArgString(Index - 1));
137 case MultiArgClass: {
Sylvestre Ledruf3477c12012-09-27 10:16:10 +0000138 // Matches iff this is an exact match.
Michael J. Spencer43275572012-08-20 21:41:17 +0000139 // FIXME: Avoid strlen.
140 if (getName().size() != strlen(Args.getArgString(Index)))
141 return 0;
142
Michael J. Spencer04a42792012-08-21 18:51:17 +0000143 Index += 1 + getNumArgs();
Michael J. Spencer43275572012-08-20 21:41:17 +0000144 if (Index > Args.getNumInputArgStrings())
145 return 0;
146
Michael J. Spencer04a42792012-08-21 18:51:17 +0000147 Arg *A = new Arg(getUnaliasedOption(), Index - 1 - getNumArgs(),
148 Args.getArgString(Index - getNumArgs()));
149 for (unsigned i = 1; i != getNumArgs(); ++i)
150 A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
Michael J. Spencer43275572012-08-20 21:41:17 +0000151 return A;
152 }
153 case JoinedOrSeparateClass: {
154 // If this is not an exact match, it is a joined arg.
155 // FIXME: Avoid strlen.
156 if (getName().size() != strlen(Args.getArgString(Index))) {
157 const char *Value = Args.getArgString(Index) + getName().size();
158 return new Arg(this, Index++, Value);
159 }
160
161 // Otherwise it must be separate.
162 Index += 2;
163 if (Index > Args.getNumInputArgStrings())
164 return 0;
165
166 return new Arg(getUnaliasedOption(),
167 Index - 2, Args.getArgString(Index - 1));
168 }
169 case JoinedAndSeparateClass:
170 // Always matches.
171 Index += 2;
172 if (Index > Args.getNumInputArgStrings())
173 return 0;
174
175 return new Arg(getUnaliasedOption(), Index - 2,
176 Args.getArgString(Index-2)+getName().size(),
177 Args.getArgString(Index-1));
David Blaikie279e0be2012-08-20 22:22:51 +0000178 default:
179 llvm_unreachable("Invalid option kind!");
Michael J. Spencer43275572012-08-20 21:41:17 +0000180 }
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000181}