blob: a992cef3d239b2d0b1c951843ca83e07fb04f505 [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"
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000015#include <cassert>
Daniel Dunbarbbf842b2009-03-04 23:22:02 +000016#include <algorithm>
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000017using namespace clang::driver;
18
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000019Option::Option(OptionClass _Kind, OptSpecifier _ID, const char *_Name,
Mike Stump1eb44332009-09-09 15:08:12 +000020 const OptionGroup *_Group, const Option *_Alias)
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000021 : Kind(_Kind), ID(_ID.getID()), Name(_Name), Group(_Group), Alias(_Alias),
Daniel Dunbar0f9098e2009-03-04 21:05:23 +000022 Unsupported(false), LinkerInput(false), NoOptAsInput(false),
Daniel Dunbarcaeed1d2010-08-13 04:44:20 +000023 DriverOption(false), NoArgumentUnused(false), NoForward(false) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000024
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((!Alias || (!Alias->Alias && !Group)) &&
Mike Stump1eb44332009-09-09 15:08:12 +000029 "Multi-level aliases and aliases with groups are unsupported.");
Daniel Dunbare375c4a2010-06-09 22:31:04 +000030
31 // Initialize rendering options based on the class.
32 switch (Kind) {
33 case GroupClass:
34 case InputClass:
35 case UnknownClass:
36 RenderStyle = RenderValuesStyle;
37 break;
38
39 case JoinedClass:
40 case JoinedAndSeparateClass:
41 RenderStyle = RenderJoinedStyle;
42 break;
43
44 case CommaJoinedClass:
45 RenderStyle = RenderCommaJoinedStyle;
46 break;
47
48 case FlagClass:
49 case SeparateClass:
50 case MultiArgClass:
51 case JoinedOrSeparateClass:
52 RenderStyle = RenderSeparateStyle;
53 break;
54 }
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000055}
56
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000057Option::~Option() {
58}
59
60void Option::dump() const {
61 llvm::errs() << "<";
62 switch (Kind) {
63 default:
64 assert(0 && "Invalid kind");
65#define P(N) case N: llvm::errs() << #N; break
66 P(GroupClass);
67 P(InputClass);
68 P(UnknownClass);
69 P(FlagClass);
70 P(JoinedClass);
71 P(SeparateClass);
72 P(CommaJoinedClass);
73 P(MultiArgClass);
74 P(JoinedOrSeparateClass);
75 P(JoinedAndSeparateClass);
76#undef P
77 }
78
79 llvm::errs() << " Name:\"" << Name << '"';
80
81 if (Group) {
82 llvm::errs() << " Group:";
83 Group->dump();
84 }
Mike Stump1eb44332009-09-09 15:08:12 +000085
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000086 if (Alias) {
87 llvm::errs() << " Alias:";
88 Alias->dump();
89 }
Mike Stump1eb44332009-09-09 15:08:12 +000090
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000091 if (const MultiArgOption *MOA = dyn_cast<MultiArgOption>(this))
92 llvm::errs() << " NumArgs:" << MOA->getNumArgs();
93
94 llvm::errs() << ">\n";
95}
96
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000097bool Option::matches(OptSpecifier Opt) const {
Daniel Dunbarb32aa512009-11-19 03:26:50 +000098 // Aliases are never considered in matching, look through them.
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000099 if (Alias)
100 return Alias->matches(Opt);
Mike Stump1eb44332009-09-09 15:08:12 +0000101
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000102 // Check exact match.
103 if (ID == Opt)
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000104 return true;
Mike Stump1eb44332009-09-09 15:08:12 +0000105
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000106 if (Group)
107 return Group->matches(Opt);
108 return false;
109}
110
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000111OptionGroup::OptionGroup(OptSpecifier ID, const char *Name,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000112 const OptionGroup *Group)
113 : Option(Option::GroupClass, ID, Name, Group, 0) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000114}
115
Daniel Dunbar785e7962010-06-11 22:00:17 +0000116Arg *OptionGroup::accept(const ArgList &Args, unsigned &Index) const {
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000117 assert(0 && "accept() should never be called on an OptionGroup");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000118 return 0;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000119}
120
Daniel Dunbara0289fd2009-11-19 04:25:06 +0000121InputOption::InputOption(OptSpecifier ID)
122 : Option(Option::InputClass, ID, "<input>", 0, 0) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000123}
124
Daniel Dunbar785e7962010-06-11 22:00:17 +0000125Arg *InputOption::accept(const ArgList &Args, unsigned &Index) const {
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000126 assert(0 && "accept() should never be called on an InputOption");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000127 return 0;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000128}
129
Daniel Dunbara0289fd2009-11-19 04:25:06 +0000130UnknownOption::UnknownOption(OptSpecifier ID)
131 : Option(Option::UnknownClass, ID, "<unknown>", 0, 0) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000132}
133
Daniel Dunbar785e7962010-06-11 22:00:17 +0000134Arg *UnknownOption::accept(const ArgList &Args, unsigned &Index) const {
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000135 assert(0 && "accept() should never be called on an UnknownOption");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000136 return 0;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000137}
138
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000139FlagOption::FlagOption(OptSpecifier ID, const char *Name,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000140 const OptionGroup *Group, const Option *Alias)
141 : Option(Option::FlagClass, ID, Name, Group, Alias) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000142}
143
Daniel Dunbar785e7962010-06-11 22:00:17 +0000144Arg *FlagOption::accept(const ArgList &Args, unsigned &Index) const {
Mike Stump1eb44332009-09-09 15:08:12 +0000145 // Matches iff this is an exact match.
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000146 // FIXME: Avoid strlen.
147 if (strlen(getName()) != strlen(Args.getArgString(Index)))
148 return 0;
149
Daniel Dunbar3856ab32010-06-09 22:44:34 +0000150 return new Arg(getUnaliasedOption(), Index++);
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000151}
152
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000153JoinedOption::JoinedOption(OptSpecifier ID, const char *Name,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000154 const OptionGroup *Group, const Option *Alias)
155 : Option(Option::JoinedClass, ID, Name, Group, Alias) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000156}
157
Daniel Dunbar785e7962010-06-11 22:00:17 +0000158Arg *JoinedOption::accept(const ArgList &Args, unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000159 // Always matches.
Daniel Dunbar4465a772010-06-09 22:31:00 +0000160 const char *Value = Args.getArgString(Index) + strlen(getName());
Daniel Dunbar3856ab32010-06-09 22:44:34 +0000161 return new Arg(getUnaliasedOption(), Index++, Value);
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000162}
163
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000164CommaJoinedOption::CommaJoinedOption(OptSpecifier ID, const char *Name,
Mike Stump1eb44332009-09-09 15:08:12 +0000165 const OptionGroup *Group,
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000166 const Option *Alias)
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000167 : Option(Option::CommaJoinedClass, ID, Name, Group, Alias) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000168}
169
Daniel Dunbar785e7962010-06-11 22:00:17 +0000170Arg *CommaJoinedOption::accept(const ArgList &Args,
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000171 unsigned &Index) const {
Daniel Dunbar532c1ec2010-06-09 22:31:08 +0000172 // Always matches.
173 const char *Str = Args.getArgString(Index) + strlen(getName());
Daniel Dunbar3856ab32010-06-09 22:44:34 +0000174 Arg *A = new Arg(getUnaliasedOption(), Index++);
Mike Stump1eb44332009-09-09 15:08:12 +0000175
Daniel Dunbar532c1ec2010-06-09 22:31:08 +0000176 // Parse out the comma separated values.
177 const char *Prev = Str;
178 for (;; ++Str) {
179 char c = *Str;
180
181 if (!c || c == ',') {
182 if (Prev != Str) {
183 char *Value = new char[Str - Prev + 1];
184 memcpy(Value, Prev, Str - Prev);
185 Value[Str - Prev] = '\0';
186 A->getValues().push_back(Value);
187 }
188
189 if (!c)
190 break;
191
192 Prev = Str + 1;
193 }
194 }
195 A->setOwnsValues(true);
196
197 return A;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000198}
199
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000200SeparateOption::SeparateOption(OptSpecifier ID, const char *Name,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000201 const OptionGroup *Group, const Option *Alias)
202 : Option(Option::SeparateClass, ID, Name, Group, Alias) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000203}
204
Daniel Dunbar785e7962010-06-11 22:00:17 +0000205Arg *SeparateOption::accept(const ArgList &Args, unsigned &Index) const {
Mike Stump1eb44332009-09-09 15:08:12 +0000206 // Matches iff this is an exact match.
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000207 // FIXME: Avoid strlen.
208 if (strlen(getName()) != strlen(Args.getArgString(Index)))
209 return 0;
210
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000211 Index += 2;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000212 if (Index > Args.getNumInputArgStrings())
213 return 0;
214
Daniel Dunbar3856ab32010-06-09 22:44:34 +0000215 return new Arg(getUnaliasedOption(), Index - 2, Args.getArgString(Index - 1));
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000216}
217
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000218MultiArgOption::MultiArgOption(OptSpecifier ID, const char *Name,
Mike Stump1eb44332009-09-09 15:08:12 +0000219 const OptionGroup *Group, const Option *Alias,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000220 unsigned _NumArgs)
221 : Option(Option::MultiArgClass, ID, Name, Group, Alias), NumArgs(_NumArgs) {
Daniel Dunbar644eade2009-03-12 05:46:32 +0000222 assert(NumArgs > 1 && "Invalid MultiArgOption!");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000223}
224
Daniel Dunbar785e7962010-06-11 22:00:17 +0000225Arg *MultiArgOption::accept(const ArgList &Args, unsigned &Index) const {
Mike Stump1eb44332009-09-09 15:08:12 +0000226 // Matches iff this is an exact match.
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000227 // FIXME: Avoid strlen.
228 if (strlen(getName()) != strlen(Args.getArgString(Index)))
229 return 0;
230
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000231 Index += 1 + NumArgs;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000232 if (Index > Args.getNumInputArgStrings())
233 return 0;
234
Daniel Dunbar3856ab32010-06-09 22:44:34 +0000235 Arg *A = new Arg(getUnaliasedOption(), Index - 1 - NumArgs,
236 Args.getArgString(Index - NumArgs));
Daniel Dunbar4465a772010-06-09 22:31:00 +0000237 for (unsigned i = 1; i != NumArgs; ++i)
238 A->getValues().push_back(Args.getArgString(Index - NumArgs + i));
239 return A;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000240}
241
Daniel Dunbar312a8b72010-06-09 18:49:38 +0000242JoinedOrSeparateOption::JoinedOrSeparateOption(OptSpecifier ID,
243 const char *Name,
Mike Stump1eb44332009-09-09 15:08:12 +0000244 const OptionGroup *Group,
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000245 const Option *Alias)
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000246 : Option(Option::JoinedOrSeparateClass, ID, Name, Group, Alias) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000247}
248
Daniel Dunbar785e7962010-06-11 22:00:17 +0000249Arg *JoinedOrSeparateOption::accept(const ArgList &Args,
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000250 unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000251 // If this is not an exact match, it is a joined arg.
252 // FIXME: Avoid strlen.
Daniel Dunbar4465a772010-06-09 22:31:00 +0000253 if (strlen(getName()) != strlen(Args.getArgString(Index))) {
254 const char *Value = Args.getArgString(Index) + strlen(getName());
Daniel Dunbar532c1ec2010-06-09 22:31:08 +0000255 return new Arg(this, Index++, Value);
Daniel Dunbar4465a772010-06-09 22:31:00 +0000256 }
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000257
258 // Otherwise it must be separate.
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000259 Index += 2;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000260 if (Index > Args.getNumInputArgStrings())
261 return 0;
262
Daniel Dunbar3856ab32010-06-09 22:44:34 +0000263 return new Arg(getUnaliasedOption(), Index - 2, Args.getArgString(Index - 1));
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000264}
265
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000266JoinedAndSeparateOption::JoinedAndSeparateOption(OptSpecifier ID,
Mike Stump1eb44332009-09-09 15:08:12 +0000267 const char *Name,
268 const OptionGroup *Group,
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000269 const Option *Alias)
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000270 : Option(Option::JoinedAndSeparateClass, ID, Name, Group, Alias) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000271}
272
Daniel Dunbar785e7962010-06-11 22:00:17 +0000273Arg *JoinedAndSeparateOption::accept(const ArgList &Args,
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000274 unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000275 // Always matches.
276
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000277 Index += 2;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000278 if (Index > Args.getNumInputArgStrings())
279 return 0;
280
Daniel Dunbar3856ab32010-06-09 22:44:34 +0000281 return new Arg(getUnaliasedOption(), Index - 2,
282 Args.getArgString(Index-2)+strlen(getName()),
283 Args.getArgString(Index-1));
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000284}