blob: 43d7e9e476062c3643b43ec28c143d95423cec7f [file] [log] [blame]
Daniel Dunbar16090d42009-03-03 05:55:11 +00001//===--- Option.cpp - Abstract Driver Options ---------------------------*-===//
2//
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 Dunbar8e052372009-03-04 23:22:02 +000011
12#include "clang/Driver/Arg.h"
13#include "clang/Driver/ArgList.h"
Daniel Dunbara5aa4b02009-03-04 08:33:23 +000014#include "llvm/Support/raw_ostream.h"
Daniel Dunbar16090d42009-03-03 05:55:11 +000015#include <cassert>
Daniel Dunbar8e052372009-03-04 23:22:02 +000016#include <algorithm>
Daniel Dunbar16090d42009-03-03 05:55:11 +000017using namespace clang;
18using namespace clang::driver;
19
Daniel Dunbar0d96a83b2009-03-04 21:53:04 +000020Option::Option(OptionClass _Kind, options::ID _ID, const char *_Name,
Daniel Dunbara5aa4b02009-03-04 08:33:23 +000021 const OptionGroup *_Group, const Option *_Alias)
Daniel Dunbar0d96a83b2009-03-04 21:53:04 +000022 : Kind(_Kind), ID(_ID), Name(_Name), Group(_Group), Alias(_Alias),
Daniel Dunbarec0f2fa2009-03-04 21:05:23 +000023 Unsupported(false), LinkerInput(false), NoOptAsInput(false),
24 ForceSeparateRender(false), ForceJoinedRender(false)
25{
Daniel Dunbar16090d42009-03-03 05:55:11 +000026
27 // Multi-level aliases are not supported, and alias options cannot
28 // have groups. This just simplifies option tracking, it is not an
29 // inherent limitation.
30 assert((!Alias || (!Alias->Alias && !Group)) &&
31 "Multi-level aliases and aliases with groups are unsupported.");
32}
33
Daniel Dunbara5aa4b02009-03-04 08:33:23 +000034Option::~Option() {
35}
36
37void Option::dump() const {
38 llvm::errs() << "<";
39 switch (Kind) {
40 default:
41 assert(0 && "Invalid kind");
42#define P(N) case N: llvm::errs() << #N; break
43 P(GroupClass);
44 P(InputClass);
45 P(UnknownClass);
46 P(FlagClass);
47 P(JoinedClass);
48 P(SeparateClass);
49 P(CommaJoinedClass);
50 P(MultiArgClass);
51 P(JoinedOrSeparateClass);
52 P(JoinedAndSeparateClass);
53#undef P
54 }
55
56 llvm::errs() << " Name:\"" << Name << '"';
57
58 if (Group) {
59 llvm::errs() << " Group:";
60 Group->dump();
61 }
62
63 if (Alias) {
64 llvm::errs() << " Alias:";
65 Alias->dump();
66 }
67
68 if (const MultiArgOption *MOA = dyn_cast<MultiArgOption>(this))
69 llvm::errs() << " NumArgs:" << MOA->getNumArgs();
70
71 llvm::errs() << ">\n";
Daniel Dunbar8e052372009-03-04 23:22:02 +000072
73 llvm::errs().flush(); // FIXME
Daniel Dunbara5aa4b02009-03-04 08:33:23 +000074}
75
Daniel Dunbar16090d42009-03-03 05:55:11 +000076bool Option::matches(const Option *Opt) const {
77 // Aliases are never considered in matching.
78 if (Opt->getAlias())
79 return matches(Opt->getAlias());
80 if (Alias)
81 return Alias->matches(Opt);
82
83 if (this == Opt)
84 return true;
85
86 if (Group)
87 return Group->matches(Opt);
88 return false;
89}
90
Daniel Dunbar0d96a83b2009-03-04 21:53:04 +000091OptionGroup::OptionGroup(options::ID ID, const char *Name,
92 const OptionGroup *Group)
93 : Option(Option::GroupClass, ID, Name, Group, 0) {
Daniel Dunbara5aa4b02009-03-04 08:33:23 +000094}
95
Daniel Dunbar0119ee42009-03-04 20:53:00 +000096Arg *OptionGroup::accept(const ArgList &Args, unsigned &Index) const {
Daniel Dunbara5aa4b02009-03-04 08:33:23 +000097 assert(0 && "FIXME");
98 return 0;
Daniel Dunbar16090d42009-03-03 05:55:11 +000099}
100
101InputOption::InputOption()
Daniel Dunbar0d96a83b2009-03-04 21:53:04 +0000102 : Option(Option::InputClass, options::InputOpt, "<input>", 0, 0) {
Daniel Dunbara5aa4b02009-03-04 08:33:23 +0000103}
104
Daniel Dunbar0119ee42009-03-04 20:53:00 +0000105Arg *InputOption::accept(const ArgList &Args, unsigned &Index) const {
Daniel Dunbara5aa4b02009-03-04 08:33:23 +0000106 assert(0 && "FIXME");
107 return 0;
Daniel Dunbar16090d42009-03-03 05:55:11 +0000108}
109
110UnknownOption::UnknownOption()
Daniel Dunbar0d96a83b2009-03-04 21:53:04 +0000111 : Option(Option::UnknownClass, options::UnknownOpt, "<unknown>", 0, 0) {
Daniel Dunbar16090d42009-03-03 05:55:11 +0000112}
113
Daniel Dunbar0119ee42009-03-04 20:53:00 +0000114Arg *UnknownOption::accept(const ArgList &Args, unsigned &Index) const {
Daniel Dunbara5aa4b02009-03-04 08:33:23 +0000115 assert(0 && "FIXME");
116 return 0;
Daniel Dunbar16090d42009-03-03 05:55:11 +0000117}
118
Daniel Dunbar0d96a83b2009-03-04 21:53:04 +0000119FlagOption::FlagOption(options::ID ID, const char *Name,
120 const OptionGroup *Group, const Option *Alias)
121 : Option(Option::FlagClass, ID, Name, Group, Alias) {
Daniel Dunbar16090d42009-03-03 05:55:11 +0000122}
123
Daniel Dunbar0119ee42009-03-04 20:53:00 +0000124Arg *FlagOption::accept(const ArgList &Args, unsigned &Index) const {
Daniel Dunbar8e052372009-03-04 23:22:02 +0000125 // Matches iff this is an exact match.
126 // FIXME: Avoid strlen.
127 if (strlen(getName()) != strlen(Args.getArgString(Index)))
128 return 0;
129
130 return new PositionalArg(this, Index++);
Daniel Dunbar16090d42009-03-03 05:55:11 +0000131}
132
Daniel Dunbar0d96a83b2009-03-04 21:53:04 +0000133JoinedOption::JoinedOption(options::ID ID, const char *Name,
134 const OptionGroup *Group, const Option *Alias)
135 : Option(Option::JoinedClass, ID, Name, Group, Alias) {
Daniel Dunbar16090d42009-03-03 05:55:11 +0000136}
137
Daniel Dunbar0119ee42009-03-04 20:53:00 +0000138Arg *JoinedOption::accept(const ArgList &Args, unsigned &Index) const {
Daniel Dunbar8e052372009-03-04 23:22:02 +0000139 // Always matches.
140 return new JoinedArg(this, Index++);
Daniel Dunbara5aa4b02009-03-04 08:33:23 +0000141}
142
Daniel Dunbar0d96a83b2009-03-04 21:53:04 +0000143CommaJoinedOption::CommaJoinedOption(options::ID ID, const char *Name,
144 const OptionGroup *Group,
Daniel Dunbara5aa4b02009-03-04 08:33:23 +0000145 const Option *Alias)
Daniel Dunbar0d96a83b2009-03-04 21:53:04 +0000146 : Option(Option::CommaJoinedClass, ID, Name, Group, Alias) {
Daniel Dunbara5aa4b02009-03-04 08:33:23 +0000147}
148
Daniel Dunbar0119ee42009-03-04 20:53:00 +0000149Arg *CommaJoinedOption::accept(const ArgList &Args, unsigned &Index) const {
Daniel Dunbar8e052372009-03-04 23:22:02 +0000150 // Always matches. We count the commas now so we can answer
151 // getNumValues easily.
152
153 // Get the suffix string.
154 // FIXME: Avoid strlen, and move to helper method?
155 const char *Suffix = Args.getArgString(Index) + strlen(getName());
156 const char *SuffixEnd = Suffix + strlen(Suffix);
157
158 // Degenerate case, exact match has no values.
159 if (Suffix == SuffixEnd)
160 return new CommaJoinedArg(this, Index++, 0);
161
162 return new CommaJoinedArg(this, Index++,
163 std::count(Suffix, SuffixEnd, ',') + 1);
Daniel Dunbara5aa4b02009-03-04 08:33:23 +0000164}
165
Daniel Dunbar0d96a83b2009-03-04 21:53:04 +0000166SeparateOption::SeparateOption(options::ID ID, const char *Name,
167 const OptionGroup *Group, const Option *Alias)
168 : Option(Option::SeparateClass, ID, Name, Group, Alias) {
Daniel Dunbara5aa4b02009-03-04 08:33:23 +0000169}
170
Daniel Dunbar0119ee42009-03-04 20:53:00 +0000171Arg *SeparateOption::accept(const ArgList &Args, unsigned &Index) const {
Daniel Dunbar8e052372009-03-04 23:22:02 +0000172 // Matches iff this is an exact match.
173 // FIXME: Avoid strlen.
174 if (strlen(getName()) != strlen(Args.getArgString(Index)))
175 return 0;
176
177 // FIXME: Missing argument error.
178 Index += 2;
179 return new SeparateArg(this, Index - 2, 1);
Daniel Dunbara5aa4b02009-03-04 08:33:23 +0000180}
181
Daniel Dunbar0d96a83b2009-03-04 21:53:04 +0000182MultiArgOption::MultiArgOption(options::ID ID, const char *Name,
183 const OptionGroup *Group, const Option *Alias,
184 unsigned _NumArgs)
185 : Option(Option::MultiArgClass, ID, Name, Group, Alias), NumArgs(_NumArgs) {
Daniel Dunbara5aa4b02009-03-04 08:33:23 +0000186}
187
Daniel Dunbar0119ee42009-03-04 20:53:00 +0000188Arg *MultiArgOption::accept(const ArgList &Args, unsigned &Index) const {
Daniel Dunbar8e052372009-03-04 23:22:02 +0000189 // Matches iff this is an exact match.
190 // FIXME: Avoid strlen.
191 if (strlen(getName()) != strlen(Args.getArgString(Index)))
192 return 0;
193
194 // FIXME: Missing argument error.
195 Index += 1 + NumArgs;
196 return new SeparateArg(this, Index - 1 - NumArgs, NumArgs);
Daniel Dunbar16090d42009-03-03 05:55:11 +0000197}
198
Daniel Dunbar0d96a83b2009-03-04 21:53:04 +0000199JoinedOrSeparateOption::JoinedOrSeparateOption(options::ID ID, const char *Name,
Daniel Dunbara5aa4b02009-03-04 08:33:23 +0000200 const OptionGroup *Group,
201 const Option *Alias)
Daniel Dunbar0d96a83b2009-03-04 21:53:04 +0000202 : Option(Option::JoinedOrSeparateClass, ID, Name, Group, Alias) {
Daniel Dunbara5aa4b02009-03-04 08:33:23 +0000203}
204
Daniel Dunbar0119ee42009-03-04 20:53:00 +0000205Arg *JoinedOrSeparateOption::accept(const ArgList &Args, unsigned &Index) const {
Daniel Dunbar8e052372009-03-04 23:22:02 +0000206 // If this is not an exact match, it is a joined arg.
207 // FIXME: Avoid strlen.
208 if (strlen(getName()) != strlen(Args.getArgString(Index)))
209 return new JoinedArg(this, Index++);
210
211 // Otherwise it must be separate.
212 // FIXME: Missing argument error.
213 Index += 2;
214 return new SeparateArg(this, Index - 2, 1);
Daniel Dunbar16090d42009-03-03 05:55:11 +0000215}
216
Daniel Dunbar0d96a83b2009-03-04 21:53:04 +0000217JoinedAndSeparateOption::JoinedAndSeparateOption(options::ID ID,
218 const char *Name,
Daniel Dunbara5aa4b02009-03-04 08:33:23 +0000219 const OptionGroup *Group,
220 const Option *Alias)
Daniel Dunbar0d96a83b2009-03-04 21:53:04 +0000221 : Option(Option::JoinedAndSeparateClass, ID, Name, Group, Alias) {
Daniel Dunbar16090d42009-03-03 05:55:11 +0000222}
223
Daniel Dunbar0119ee42009-03-04 20:53:00 +0000224Arg *JoinedAndSeparateOption::accept(const ArgList &Args, unsigned &Index) const {
Daniel Dunbar8e052372009-03-04 23:22:02 +0000225 // Always matches.
226
227 // FIXME: Missing argument error.
228 Index += 2;
229 return new JoinedAndSeparateArg(this, Index - 2);
Daniel Dunbara5aa4b02009-03-04 08:33:23 +0000230}
Daniel Dunbar16090d42009-03-03 05:55:11 +0000231