blob: 57eaee22136c55e3e8f70032e6ceeaa5014446dc [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. Spencer04a42792012-08-21 18:51:17 +000020Option::Option(const OptTable::Info *info, OptSpecifier _ID,
21 const Option *_Group, const Option *_Alias)
22 : Info(info), ID(_ID.getID()), Group(_Group), Alias(_Alias) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000023
24 // Multi-level aliases are not supported, and alias options cannot
25 // have groups. This just simplifies option tracking, it is not an
26 // inherent limitation.
27 assert((!Alias || (!Alias->Alias && !Group)) &&
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
53 if (Group) {
54 llvm::errs() << " Group:";
55 Group->dump();
56 }
Mike Stump1eb44332009-09-09 15:08:12 +000057
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000058 if (Alias) {
59 llvm::errs() << " Alias:";
60 Alias->dump();
61 }
Mike Stump1eb44332009-09-09 15:08:12 +000062
Michael J. Spencer04a42792012-08-21 18:51:17 +000063 if (getKind() == MultiArgClass)
64 llvm::errs() << " NumArgs:" << getNumArgs();
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000065
66 llvm::errs() << ">\n";
67}
68
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000069bool Option::matches(OptSpecifier Opt) const {
Daniel Dunbarb32aa512009-11-19 03:26:50 +000070 // Aliases are never considered in matching, look through them.
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000071 if (Alias)
72 return Alias->matches(Opt);
Mike Stump1eb44332009-09-09 15:08:12 +000073
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000074 // Check exact match.
75 if (ID == Opt)
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000076 return true;
Mike Stump1eb44332009-09-09 15:08:12 +000077
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000078 if (Group)
79 return Group->matches(Opt);
80 return false;
81}
82
Michael J. Spencer43275572012-08-20 21:41:17 +000083Arg *Option::accept(const ArgList &Args, unsigned &Index) const {
Michael J. Spencer04a42792012-08-21 18:51:17 +000084 switch (getKind()) {
Michael J. Spencer43275572012-08-20 21:41:17 +000085 case FlagClass:
86 if (getName().size() != strlen(Args.getArgString(Index)))
87 return 0;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000088
Michael J. Spencer43275572012-08-20 21:41:17 +000089 return new Arg(getUnaliasedOption(), Index++);
90 case JoinedClass: {
Douglas Gregorbcf6a802011-07-05 16:56:25 +000091 const char *Value = Args.getArgString(Index) + getName().size();
Michael J. Spencer43275572012-08-20 21:41:17 +000092 return new Arg(getUnaliasedOption(), Index++, Value);
Daniel Dunbar4465a772010-06-09 22:31:00 +000093 }
Michael J. Spencer43275572012-08-20 21:41:17 +000094 case CommaJoinedClass: {
95 // Always matches.
96 const char *Str = Args.getArgString(Index) + getName().size();
97 Arg *A = new Arg(getUnaliasedOption(), Index++);
Daniel Dunbarbbf842b2009-03-04 23:22:02 +000098
Michael J. Spencer43275572012-08-20 21:41:17 +000099 // Parse out the comma separated values.
100 const char *Prev = Str;
101 for (;; ++Str) {
102 char c = *Str;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000103
Michael J. Spencer43275572012-08-20 21:41:17 +0000104 if (!c || c == ',') {
105 if (Prev != Str) {
106 char *Value = new char[Str - Prev + 1];
107 memcpy(Value, Prev, Str - Prev);
108 Value[Str - Prev] = '\0';
109 A->getValues().push_back(Value);
110 }
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000111
Michael J. Spencer43275572012-08-20 21:41:17 +0000112 if (!c)
113 break;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000114
Michael J. Spencer43275572012-08-20 21:41:17 +0000115 Prev = Str + 1;
116 }
117 }
118 A->setOwnsValues(true);
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000119
Michael J. Spencer43275572012-08-20 21:41:17 +0000120 return A;
121 }
122 case SeparateClass:
123 // Matches iff this is an exact match.
124 // FIXME: Avoid strlen.
125 if (getName().size() != strlen(Args.getArgString(Index)))
126 return 0;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000127
Michael J. Spencer43275572012-08-20 21:41:17 +0000128 Index += 2;
129 if (Index > Args.getNumInputArgStrings())
130 return 0;
131
132 return new Arg(getUnaliasedOption(),
133 Index - 2, Args.getArgString(Index - 1));
134 case MultiArgClass: {
135 // Matches iff this is an exact match.
136 // FIXME: Avoid strlen.
137 if (getName().size() != strlen(Args.getArgString(Index)))
138 return 0;
139
Michael J. Spencer04a42792012-08-21 18:51:17 +0000140 Index += 1 + getNumArgs();
Michael J. Spencer43275572012-08-20 21:41:17 +0000141 if (Index > Args.getNumInputArgStrings())
142 return 0;
143
Michael J. Spencer04a42792012-08-21 18:51:17 +0000144 Arg *A = new Arg(getUnaliasedOption(), Index - 1 - getNumArgs(),
145 Args.getArgString(Index - getNumArgs()));
146 for (unsigned i = 1; i != getNumArgs(); ++i)
147 A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
Michael J. Spencer43275572012-08-20 21:41:17 +0000148 return A;
149 }
150 case JoinedOrSeparateClass: {
151 // If this is not an exact match, it is a joined arg.
152 // FIXME: Avoid strlen.
153 if (getName().size() != strlen(Args.getArgString(Index))) {
154 const char *Value = Args.getArgString(Index) + getName().size();
155 return new Arg(this, Index++, Value);
156 }
157
158 // Otherwise it must be separate.
159 Index += 2;
160 if (Index > Args.getNumInputArgStrings())
161 return 0;
162
163 return new Arg(getUnaliasedOption(),
164 Index - 2, Args.getArgString(Index - 1));
165 }
166 case JoinedAndSeparateClass:
167 // Always matches.
168 Index += 2;
169 if (Index > Args.getNumInputArgStrings())
170 return 0;
171
172 return new Arg(getUnaliasedOption(), Index - 2,
173 Args.getArgString(Index-2)+getName().size(),
174 Args.getArgString(Index-1));
David Blaikie279e0be2012-08-20 22:22:51 +0000175 default:
176 llvm_unreachable("Invalid option kind!");
Michael J. Spencer43275572012-08-20 21:41:17 +0000177 }
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000178}