blob: a250d8740a9748340ea8acc6a1d510f6c2b3e417 [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. Spencer0464fd52012-10-10 21:48:26 +000026 assert((!getAlias().isValid() || (!getAlias().getAlias().isValid() &&
27 !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. Spencer04a42792012-08-21 18:51:17 +000051 llvm::errs() << " Name:\"" << getName() << '"';
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000052
Michael J. Spencer0464fd52012-10-10 21:48:26 +000053 const Option Group = getGroup();
54 if (Group.isValid()) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000055 llvm::errs() << " Group:";
Michael J. Spencer0464fd52012-10-10 21:48:26 +000056 Group.dump();
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000057 }
Mike Stump1eb44332009-09-09 15:08:12 +000058
Michael J. Spencer0464fd52012-10-10 21:48:26 +000059 const Option Alias = getAlias();
60 if (Alias.isValid()) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000061 llvm::errs() << " Alias:";
Michael J. Spencer0464fd52012-10-10 21:48:26 +000062 Alias.dump();
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000063 }
Mike Stump1eb44332009-09-09 15:08:12 +000064
Michael J. Spencer04a42792012-08-21 18:51:17 +000065 if (getKind() == MultiArgClass)
66 llvm::errs() << " NumArgs:" << getNumArgs();
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000067
68 llvm::errs() << ">\n";
69}
70
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000071bool Option::matches(OptSpecifier Opt) const {
Daniel Dunbarb32aa512009-11-19 03:26:50 +000072 // Aliases are never considered in matching, look through them.
Michael J. Spencer0464fd52012-10-10 21:48:26 +000073 const Option Alias = getAlias();
74 if (Alias.isValid())
75 return Alias.matches(Opt);
Mike Stump1eb44332009-09-09 15:08:12 +000076
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000077 // Check exact match.
Michael J. Spencer663117a2012-09-25 23:12:48 +000078 if (getID() == Opt.getID())
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000079 return true;
Mike Stump1eb44332009-09-09 15:08:12 +000080
Michael J. Spencer0464fd52012-10-10 21:48:26 +000081 const Option Group = getGroup();
82 if (Group.isValid())
83 return Group.matches(Opt);
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000084 return false;
85}
86
Michael J. Spencer43275572012-08-20 21:41:17 +000087Arg *Option::accept(const ArgList &Args, unsigned &Index) const {
Michael J. Spencer04a42792012-08-21 18:51:17 +000088 switch (getKind()) {
Michael J. Spencer43275572012-08-20 21:41:17 +000089 case FlagClass:
90 if (getName().size() != strlen(Args.getArgString(Index)))
91 return 0;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000092
Michael J. Spencer43275572012-08-20 21:41:17 +000093 return new Arg(getUnaliasedOption(), Index++);
94 case JoinedClass: {
Douglas Gregorbcf6a802011-07-05 16:56:25 +000095 const char *Value = Args.getArgString(Index) + getName().size();
Michael J. Spencer43275572012-08-20 21:41:17 +000096 return new Arg(getUnaliasedOption(), Index++, Value);
Daniel Dunbar4465a772010-06-09 22:31:00 +000097 }
Michael J. Spencer43275572012-08-20 21:41:17 +000098 case CommaJoinedClass: {
99 // Always matches.
100 const char *Str = Args.getArgString(Index) + getName().size();
101 Arg *A = new Arg(getUnaliasedOption(), Index++);
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000102
Michael J. Spencer43275572012-08-20 21:41:17 +0000103 // Parse out the comma separated values.
104 const char *Prev = Str;
105 for (;; ++Str) {
106 char c = *Str;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000107
Michael J. Spencer43275572012-08-20 21:41:17 +0000108 if (!c || c == ',') {
109 if (Prev != Str) {
110 char *Value = new char[Str - Prev + 1];
111 memcpy(Value, Prev, Str - Prev);
112 Value[Str - Prev] = '\0';
113 A->getValues().push_back(Value);
114 }
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000115
Michael J. Spencer43275572012-08-20 21:41:17 +0000116 if (!c)
117 break;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000118
Michael J. Spencer43275572012-08-20 21:41:17 +0000119 Prev = Str + 1;
120 }
121 }
122 A->setOwnsValues(true);
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000123
Michael J. Spencer43275572012-08-20 21:41:17 +0000124 return A;
125 }
126 case SeparateClass:
Sylvestre Ledruf3477c12012-09-27 10:16:10 +0000127 // Matches iff this is an exact match.
Michael J. Spencer43275572012-08-20 21:41:17 +0000128 // FIXME: Avoid strlen.
129 if (getName().size() != strlen(Args.getArgString(Index)))
130 return 0;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000131
Michael J. Spencer43275572012-08-20 21:41:17 +0000132 Index += 2;
133 if (Index > Args.getNumInputArgStrings())
134 return 0;
135
136 return new Arg(getUnaliasedOption(),
137 Index - 2, Args.getArgString(Index - 1));
138 case MultiArgClass: {
Sylvestre Ledruf3477c12012-09-27 10:16:10 +0000139 // Matches iff this is an exact match.
Michael J. Spencer43275572012-08-20 21:41:17 +0000140 // FIXME: Avoid strlen.
141 if (getName().size() != strlen(Args.getArgString(Index)))
142 return 0;
143
Michael J. Spencer04a42792012-08-21 18:51:17 +0000144 Index += 1 + getNumArgs();
Michael J. Spencer43275572012-08-20 21:41:17 +0000145 if (Index > Args.getNumInputArgStrings())
146 return 0;
147
Michael J. Spencer04a42792012-08-21 18:51:17 +0000148 Arg *A = new Arg(getUnaliasedOption(), Index - 1 - getNumArgs(),
149 Args.getArgString(Index - getNumArgs()));
150 for (unsigned i = 1; i != getNumArgs(); ++i)
151 A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
Michael J. Spencer43275572012-08-20 21:41:17 +0000152 return A;
153 }
154 case JoinedOrSeparateClass: {
155 // If this is not an exact match, it is a joined arg.
156 // FIXME: Avoid strlen.
157 if (getName().size() != strlen(Args.getArgString(Index))) {
158 const char *Value = Args.getArgString(Index) + getName().size();
Michael J. Spencer0464fd52012-10-10 21:48:26 +0000159 return new Arg(*this, Index++, Value);
Michael J. Spencer43275572012-08-20 21:41:17 +0000160 }
161
162 // Otherwise it must be separate.
163 Index += 2;
164 if (Index > Args.getNumInputArgStrings())
165 return 0;
166
167 return new Arg(getUnaliasedOption(),
168 Index - 2, Args.getArgString(Index - 1));
169 }
170 case JoinedAndSeparateClass:
171 // Always matches.
172 Index += 2;
173 if (Index > Args.getNumInputArgStrings())
174 return 0;
175
176 return new Arg(getUnaliasedOption(), Index - 2,
177 Args.getArgString(Index-2)+getName().size(),
178 Args.getArgString(Index-1));
David Blaikie279e0be2012-08-20 22:22:51 +0000179 default:
180 llvm_unreachable("Invalid option kind!");
Michael J. Spencer43275572012-08-20 21:41:17 +0000181 }
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000182}