• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- ArgList.cpp - Argument List Management ---------------------------===//
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/ArgList.h"
11 #include "clang/Driver/Arg.h"
12 #include "clang/Driver/DriverDiagnostic.h"
13 #include "clang/Driver/Option.h"
14 
15 #include "llvm/ADT/SmallString.h"
16 #include "llvm/ADT/Twine.h"
17 #include "llvm/Support/raw_ostream.h"
18 
19 using namespace clang;
20 using namespace clang::driver;
21 
SkipToNextArg()22 void arg_iterator::SkipToNextArg() {
23   for (; Current != Args.end(); ++Current) {
24     // Done if there are no filters.
25     if (!Id0.isValid())
26       break;
27 
28     // Otherwise require a match.
29     const Option &O = (*Current)->getOption();
30     if (O.matches(Id0) ||
31         (Id1.isValid() && O.matches(Id1)) ||
32         (Id2.isValid() && O.matches(Id2)))
33       break;
34   }
35 }
36 
37 //
38 
ArgList()39 ArgList::ArgList() {
40 }
41 
~ArgList()42 ArgList::~ArgList() {
43 }
44 
append(Arg * A)45 void ArgList::append(Arg *A) {
46   Args.push_back(A);
47 }
48 
getLastArgNoClaim(OptSpecifier Id) const49 Arg *ArgList::getLastArgNoClaim(OptSpecifier Id) const {
50   // FIXME: Make search efficient?
51   for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it)
52     if ((*it)->getOption().matches(Id))
53       return *it;
54   return 0;
55 }
56 
getLastArg(OptSpecifier Id) const57 Arg *ArgList::getLastArg(OptSpecifier Id) const {
58   Arg *Res = 0;
59   for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
60     if ((*it)->getOption().matches(Id)) {
61       Res = *it;
62       Res->claim();
63     }
64   }
65 
66   return Res;
67 }
68 
getLastArg(OptSpecifier Id0,OptSpecifier Id1) const69 Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1) const {
70   Arg *Res = 0;
71   for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
72     if ((*it)->getOption().matches(Id0) ||
73         (*it)->getOption().matches(Id1)) {
74       Res = *it;
75       Res->claim();
76 
77     }
78   }
79 
80   return Res;
81 }
82 
getLastArg(OptSpecifier Id0,OptSpecifier Id1,OptSpecifier Id2) const83 Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
84                          OptSpecifier Id2) const {
85   Arg *Res = 0;
86   for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
87     if ((*it)->getOption().matches(Id0) ||
88         (*it)->getOption().matches(Id1) ||
89         (*it)->getOption().matches(Id2)) {
90       Res = *it;
91       Res->claim();
92     }
93   }
94 
95   return Res;
96 }
97 
getLastArg(OptSpecifier Id0,OptSpecifier Id1,OptSpecifier Id2,OptSpecifier Id3) const98 Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
99                          OptSpecifier Id2, OptSpecifier Id3) const {
100   Arg *Res = 0;
101   for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
102     if ((*it)->getOption().matches(Id0) ||
103         (*it)->getOption().matches(Id1) ||
104         (*it)->getOption().matches(Id2) ||
105         (*it)->getOption().matches(Id3)) {
106       Res = *it;
107       Res->claim();
108     }
109   }
110 
111   return Res;
112 }
113 
hasFlag(OptSpecifier Pos,OptSpecifier Neg,bool Default) const114 bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const {
115   if (Arg *A = getLastArg(Pos, Neg))
116     return A->getOption().matches(Pos);
117   return Default;
118 }
119 
getLastArgValue(OptSpecifier Id,llvm::StringRef Default) const120 llvm::StringRef ArgList::getLastArgValue(OptSpecifier Id,
121                                          llvm::StringRef Default) const {
122   if (Arg *A = getLastArg(Id))
123     return A->getValue(*this);
124   return Default;
125 }
126 
getLastArgIntValue(OptSpecifier Id,int Default,clang::Diagnostic & Diags) const127 int ArgList::getLastArgIntValue(OptSpecifier Id, int Default,
128                                 clang::Diagnostic &Diags) const {
129   int Res = Default;
130 
131   if (Arg *A = getLastArg(Id)) {
132     if (llvm::StringRef(A->getValue(*this)).getAsInteger(10, Res))
133       Diags.Report(diag::err_drv_invalid_int_value)
134         << A->getAsString(*this) << A->getValue(*this);
135   }
136 
137   return Res;
138 }
139 
getAllArgValues(OptSpecifier Id) const140 std::vector<std::string> ArgList::getAllArgValues(OptSpecifier Id) const {
141   llvm::SmallVector<const char *, 16> Values;
142   AddAllArgValues(Values, Id);
143   return std::vector<std::string>(Values.begin(), Values.end());
144 }
145 
AddLastArg(ArgStringList & Output,OptSpecifier Id) const146 void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const {
147   if (Arg *A = getLastArg(Id)) {
148     A->claim();
149     A->render(*this, Output);
150   }
151 }
152 
AddAllArgs(ArgStringList & Output,OptSpecifier Id0,OptSpecifier Id1,OptSpecifier Id2) const153 void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
154                          OptSpecifier Id1, OptSpecifier Id2) const {
155   for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
156          ie = filtered_end(); it != ie; ++it) {
157     (*it)->claim();
158     (*it)->render(*this, Output);
159   }
160 }
161 
AddAllArgValues(ArgStringList & Output,OptSpecifier Id0,OptSpecifier Id1,OptSpecifier Id2) const162 void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
163                               OptSpecifier Id1, OptSpecifier Id2) const {
164   for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
165          ie = filtered_end(); it != ie; ++it) {
166     (*it)->claim();
167     for (unsigned i = 0, e = (*it)->getNumValues(); i != e; ++i)
168       Output.push_back((*it)->getValue(*this, i));
169   }
170 }
171 
AddAllArgsTranslated(ArgStringList & Output,OptSpecifier Id0,const char * Translation,bool Joined) const172 void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
173                                    const char *Translation,
174                                    bool Joined) const {
175   for (arg_iterator it = filtered_begin(Id0),
176          ie = filtered_end(); it != ie; ++it) {
177     (*it)->claim();
178 
179     if (Joined) {
180       Output.push_back(MakeArgString(llvm::StringRef(Translation) +
181                                      (*it)->getValue(*this, 0)));
182     } else {
183       Output.push_back(Translation);
184       Output.push_back((*it)->getValue(*this, 0));
185     }
186   }
187 }
188 
ClaimAllArgs(OptSpecifier Id0) const189 void ArgList::ClaimAllArgs(OptSpecifier Id0) const {
190   for (arg_iterator it = filtered_begin(Id0),
191          ie = filtered_end(); it != ie; ++it)
192     (*it)->claim();
193 }
194 
MakeArgString(const llvm::Twine & T) const195 const char *ArgList::MakeArgString(const llvm::Twine &T) const {
196   llvm::SmallString<256> Str;
197   T.toVector(Str);
198   return MakeArgString(Str.str());
199 }
200 
GetOrMakeJoinedArgString(unsigned Index,llvm::StringRef LHS,llvm::StringRef RHS) const201 const char *ArgList::GetOrMakeJoinedArgString(unsigned Index,
202                                               llvm::StringRef LHS,
203                                               llvm::StringRef RHS) const {
204   llvm::StringRef Cur = getArgString(Index);
205   if (Cur.size() == LHS.size() + RHS.size() &&
206       Cur.startswith(LHS) && Cur.endswith(RHS))
207     return Cur.data();
208 
209   return MakeArgString(LHS + RHS);
210 }
211 
212 //
213 
InputArgList(const char * const * ArgBegin,const char * const * ArgEnd)214 InputArgList::InputArgList(const char* const *ArgBegin,
215                            const char* const *ArgEnd)
216   : NumInputArgStrings(ArgEnd - ArgBegin) {
217   ArgStrings.append(ArgBegin, ArgEnd);
218 }
219 
~InputArgList()220 InputArgList::~InputArgList() {
221   // An InputArgList always owns its arguments.
222   for (iterator it = begin(), ie = end(); it != ie; ++it)
223     delete *it;
224 }
225 
MakeIndex(llvm::StringRef String0) const226 unsigned InputArgList::MakeIndex(llvm::StringRef String0) const {
227   unsigned Index = ArgStrings.size();
228 
229   // Tuck away so we have a reliable const char *.
230   SynthesizedStrings.push_back(String0);
231   ArgStrings.push_back(SynthesizedStrings.back().c_str());
232 
233   return Index;
234 }
235 
MakeIndex(llvm::StringRef String0,llvm::StringRef String1) const236 unsigned InputArgList::MakeIndex(llvm::StringRef String0,
237                                  llvm::StringRef String1) const {
238   unsigned Index0 = MakeIndex(String0);
239   unsigned Index1 = MakeIndex(String1);
240   assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!");
241   (void) Index1;
242   return Index0;
243 }
244 
MakeArgString(llvm::StringRef Str) const245 const char *InputArgList::MakeArgString(llvm::StringRef Str) const {
246   return getArgString(MakeIndex(Str));
247 }
248 
249 //
250 
DerivedArgList(const InputArgList & _BaseArgs)251 DerivedArgList::DerivedArgList(const InputArgList &_BaseArgs)
252   : BaseArgs(_BaseArgs) {
253 }
254 
~DerivedArgList()255 DerivedArgList::~DerivedArgList() {
256   // We only own the arguments we explicitly synthesized.
257   for (iterator it = SynthesizedArgs.begin(), ie = SynthesizedArgs.end();
258        it != ie; ++it)
259     delete *it;
260 }
261 
MakeArgString(llvm::StringRef Str) const262 const char *DerivedArgList::MakeArgString(llvm::StringRef Str) const {
263   return BaseArgs.MakeArgString(Str);
264 }
265 
MakeFlagArg(const Arg * BaseArg,const Option * Opt) const266 Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option *Opt) const {
267   Arg *A = new Arg(Opt, BaseArgs.MakeIndex(Opt->getName()), BaseArg);
268   SynthesizedArgs.push_back(A);
269   return A;
270 }
271 
MakePositionalArg(const Arg * BaseArg,const Option * Opt,llvm::StringRef Value) const272 Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option *Opt,
273                                        llvm::StringRef Value) const {
274   unsigned Index = BaseArgs.MakeIndex(Value);
275   Arg *A = new Arg(Opt, Index, BaseArgs.getArgString(Index), BaseArg);
276   SynthesizedArgs.push_back(A);
277   return A;
278 }
279 
MakeSeparateArg(const Arg * BaseArg,const Option * Opt,llvm::StringRef Value) const280 Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option *Opt,
281                                      llvm::StringRef Value) const {
282   unsigned Index = BaseArgs.MakeIndex(Opt->getName(), Value);
283   Arg *A = new Arg(Opt, Index, BaseArgs.getArgString(Index + 1), BaseArg);
284   SynthesizedArgs.push_back(A);
285   return A;
286 }
287 
MakeJoinedArg(const Arg * BaseArg,const Option * Opt,llvm::StringRef Value) const288 Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option *Opt,
289                                    llvm::StringRef Value) const {
290   unsigned Index = BaseArgs.MakeIndex(Opt->getName().str() + Value.str());
291   Arg *A = new Arg(Opt, Index,
292                    BaseArgs.getArgString(Index) + Opt->getName().size(),
293                    BaseArg);
294   SynthesizedArgs.push_back(A);
295   return A;
296 }
297