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 "llvm/Option/ArgList.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/SmallString.h"
13 #include "llvm/ADT/Twine.h"
14 #include "llvm/Option/Arg.h"
15 #include "llvm/Option/Option.h"
16 #include "llvm/Support/raw_ostream.h"
17 
18 using namespace llvm;
19 using namespace llvm::opt;
20 
SkipToNextArg()21 void arg_iterator::SkipToNextArg() {
22   for (; Current != Args.end(); ++Current) {
23     // Done if there are no filters.
24     if (!Id0.isValid())
25       break;
26 
27     // Otherwise require a match.
28     const Option &O = (*Current)->getOption();
29     if (O.matches(Id0) ||
30         (Id1.isValid() && O.matches(Id1)) ||
31         (Id2.isValid() && O.matches(Id2)))
32       break;
33   }
34 }
35 
~ArgList()36 ArgList::~ArgList() {
37 }
38 
append(Arg * A)39 void ArgList::append(Arg *A) {
40   Args.push_back(A);
41 }
42 
eraseArg(OptSpecifier Id)43 void ArgList::eraseArg(OptSpecifier Id) {
44   Args.erase(std::remove_if(begin(), end(),
45                             [=](Arg *A) { return A->getOption().matches(Id); }),
46              end());
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 nullptr;
55 }
56 
getLastArgNoClaim(OptSpecifier Id0,OptSpecifier Id1) const57 Arg *ArgList::getLastArgNoClaim(OptSpecifier Id0, OptSpecifier Id1) const {
58   // FIXME: Make search efficient?
59   for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it)
60     if ((*it)->getOption().matches(Id0) ||
61         (*it)->getOption().matches(Id1))
62       return *it;
63   return nullptr;
64 }
65 
getLastArgNoClaim(OptSpecifier Id0,OptSpecifier Id1,OptSpecifier Id2) const66 Arg *ArgList::getLastArgNoClaim(OptSpecifier Id0, OptSpecifier Id1,
67                                 OptSpecifier Id2) const {
68   // FIXME: Make search efficient?
69   for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it)
70     if ((*it)->getOption().matches(Id0) || (*it)->getOption().matches(Id1) ||
71         (*it)->getOption().matches(Id2))
72       return *it;
73   return nullptr;
74 }
75 
getLastArgNoClaim(OptSpecifier Id0,OptSpecifier Id1,OptSpecifier Id2,OptSpecifier Id3) const76 Arg *ArgList::getLastArgNoClaim(OptSpecifier Id0, OptSpecifier Id1,
77                                 OptSpecifier Id2, OptSpecifier Id3) const {
78   // FIXME: Make search efficient?
79   for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it)
80     if ((*it)->getOption().matches(Id0) || (*it)->getOption().matches(Id1) ||
81         (*it)->getOption().matches(Id2) || (*it)->getOption().matches(Id3))
82       return *it;
83   return nullptr;
84 }
85 
getLastArg(OptSpecifier Id) const86 Arg *ArgList::getLastArg(OptSpecifier Id) const {
87   Arg *Res = nullptr;
88   for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
89     if ((*it)->getOption().matches(Id)) {
90       Res = *it;
91       Res->claim();
92     }
93   }
94 
95   return Res;
96 }
97 
getLastArg(OptSpecifier Id0,OptSpecifier Id1) const98 Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1) const {
99   Arg *Res = nullptr;
100   for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
101     if ((*it)->getOption().matches(Id0) ||
102         (*it)->getOption().matches(Id1)) {
103       Res = *it;
104       Res->claim();
105 
106     }
107   }
108 
109   return Res;
110 }
111 
getLastArg(OptSpecifier Id0,OptSpecifier Id1,OptSpecifier Id2) const112 Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
113                          OptSpecifier Id2) const {
114   Arg *Res = nullptr;
115   for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
116     if ((*it)->getOption().matches(Id0) ||
117         (*it)->getOption().matches(Id1) ||
118         (*it)->getOption().matches(Id2)) {
119       Res = *it;
120       Res->claim();
121     }
122   }
123 
124   return Res;
125 }
126 
getLastArg(OptSpecifier Id0,OptSpecifier Id1,OptSpecifier Id2,OptSpecifier Id3) const127 Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
128                          OptSpecifier Id2, OptSpecifier Id3) const {
129   Arg *Res = nullptr;
130   for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
131     if ((*it)->getOption().matches(Id0) ||
132         (*it)->getOption().matches(Id1) ||
133         (*it)->getOption().matches(Id2) ||
134         (*it)->getOption().matches(Id3)) {
135       Res = *it;
136       Res->claim();
137     }
138   }
139 
140   return Res;
141 }
142 
getLastArg(OptSpecifier Id0,OptSpecifier Id1,OptSpecifier Id2,OptSpecifier Id3,OptSpecifier Id4) const143 Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
144                          OptSpecifier Id2, OptSpecifier Id3,
145                          OptSpecifier Id4) const {
146   Arg *Res = nullptr;
147   for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
148     if ((*it)->getOption().matches(Id0) ||
149         (*it)->getOption().matches(Id1) ||
150         (*it)->getOption().matches(Id2) ||
151         (*it)->getOption().matches(Id3) ||
152         (*it)->getOption().matches(Id4)) {
153       Res = *it;
154       Res->claim();
155     }
156   }
157 
158   return Res;
159 }
160 
getLastArg(OptSpecifier Id0,OptSpecifier Id1,OptSpecifier Id2,OptSpecifier Id3,OptSpecifier Id4,OptSpecifier Id5) const161 Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
162                          OptSpecifier Id2, OptSpecifier Id3,
163                          OptSpecifier Id4, OptSpecifier Id5) const {
164   Arg *Res = nullptr;
165   for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
166     if ((*it)->getOption().matches(Id0) ||
167         (*it)->getOption().matches(Id1) ||
168         (*it)->getOption().matches(Id2) ||
169         (*it)->getOption().matches(Id3) ||
170         (*it)->getOption().matches(Id4) ||
171         (*it)->getOption().matches(Id5)) {
172       Res = *it;
173       Res->claim();
174     }
175   }
176 
177   return Res;
178 }
179 
getLastArg(OptSpecifier Id0,OptSpecifier Id1,OptSpecifier Id2,OptSpecifier Id3,OptSpecifier Id4,OptSpecifier Id5,OptSpecifier Id6) const180 Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
181                          OptSpecifier Id2, OptSpecifier Id3,
182                          OptSpecifier Id4, OptSpecifier Id5,
183                          OptSpecifier Id6) const {
184   Arg *Res = nullptr;
185   for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
186     if ((*it)->getOption().matches(Id0) ||
187         (*it)->getOption().matches(Id1) ||
188         (*it)->getOption().matches(Id2) ||
189         (*it)->getOption().matches(Id3) ||
190         (*it)->getOption().matches(Id4) ||
191         (*it)->getOption().matches(Id5) ||
192         (*it)->getOption().matches(Id6)) {
193       Res = *it;
194       Res->claim();
195     }
196   }
197 
198   return Res;
199 }
200 
getLastArg(OptSpecifier Id0,OptSpecifier Id1,OptSpecifier Id2,OptSpecifier Id3,OptSpecifier Id4,OptSpecifier Id5,OptSpecifier Id6,OptSpecifier Id7) const201 Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
202                          OptSpecifier Id2, OptSpecifier Id3,
203                          OptSpecifier Id4, OptSpecifier Id5,
204                          OptSpecifier Id6, OptSpecifier Id7) const {
205   Arg *Res = nullptr;
206   for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
207     if ((*it)->getOption().matches(Id0) ||
208         (*it)->getOption().matches(Id1) ||
209         (*it)->getOption().matches(Id2) ||
210         (*it)->getOption().matches(Id3) ||
211         (*it)->getOption().matches(Id4) ||
212         (*it)->getOption().matches(Id5) ||
213         (*it)->getOption().matches(Id6) ||
214         (*it)->getOption().matches(Id7)) {
215       Res = *it;
216       Res->claim();
217     }
218   }
219 
220   return Res;
221 }
222 
hasFlag(OptSpecifier Pos,OptSpecifier Neg,bool Default) const223 bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const {
224   if (Arg *A = getLastArg(Pos, Neg))
225     return A->getOption().matches(Pos);
226   return Default;
227 }
228 
hasFlag(OptSpecifier Pos,OptSpecifier PosAlias,OptSpecifier Neg,bool Default) const229 bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier PosAlias, OptSpecifier Neg,
230                       bool Default) const {
231   if (Arg *A = getLastArg(Pos, PosAlias, Neg))
232     return A->getOption().matches(Pos) || A->getOption().matches(PosAlias);
233   return Default;
234 }
235 
getLastArgValue(OptSpecifier Id,StringRef Default) const236 StringRef ArgList::getLastArgValue(OptSpecifier Id,
237                                          StringRef Default) const {
238   if (Arg *A = getLastArg(Id))
239     return A->getValue();
240   return Default;
241 }
242 
getAllArgValues(OptSpecifier Id) const243 std::vector<std::string> ArgList::getAllArgValues(OptSpecifier Id) const {
244   SmallVector<const char *, 16> Values;
245   AddAllArgValues(Values, Id);
246   return std::vector<std::string>(Values.begin(), Values.end());
247 }
248 
AddLastArg(ArgStringList & Output,OptSpecifier Id) const249 void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const {
250   if (Arg *A = getLastArg(Id)) {
251     A->claim();
252     A->render(*this, Output);
253   }
254 }
255 
AddLastArg(ArgStringList & Output,OptSpecifier Id0,OptSpecifier Id1) const256 void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id0,
257                          OptSpecifier Id1) const {
258   if (Arg *A = getLastArg(Id0, Id1)) {
259     A->claim();
260     A->render(*this, Output);
261   }
262 }
263 
AddAllArgs(ArgStringList & Output,OptSpecifier Id0,OptSpecifier Id1,OptSpecifier Id2) const264 void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
265                          OptSpecifier Id1, OptSpecifier Id2) const {
266   for (auto Arg: filtered(Id0, Id1, Id2)) {
267     Arg->claim();
268     Arg->render(*this, Output);
269   }
270 }
271 
AddAllArgValues(ArgStringList & Output,OptSpecifier Id0,OptSpecifier Id1,OptSpecifier Id2) const272 void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
273                               OptSpecifier Id1, OptSpecifier Id2) const {
274   for (auto Arg : filtered(Id0, Id1, Id2)) {
275     Arg->claim();
276     const auto &Values = Arg->getValues();
277     Output.append(Values.begin(), Values.end());
278   }
279 }
280 
AddAllArgsTranslated(ArgStringList & Output,OptSpecifier Id0,const char * Translation,bool Joined) const281 void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
282                                    const char *Translation,
283                                    bool Joined) const {
284   for (auto Arg: filtered(Id0)) {
285     Arg->claim();
286 
287     if (Joined) {
288       Output.push_back(MakeArgString(StringRef(Translation) +
289                                      Arg->getValue(0)));
290     } else {
291       Output.push_back(Translation);
292       Output.push_back(Arg->getValue(0));
293     }
294   }
295 }
296 
ClaimAllArgs(OptSpecifier Id0) const297 void ArgList::ClaimAllArgs(OptSpecifier Id0) const {
298   for (auto Arg : filtered(Id0))
299     Arg->claim();
300 }
301 
ClaimAllArgs() const302 void ArgList::ClaimAllArgs() const {
303   for (const_iterator it = begin(), ie = end(); it != ie; ++it)
304     if (!(*it)->isClaimed())
305       (*it)->claim();
306 }
307 
GetOrMakeJoinedArgString(unsigned Index,StringRef LHS,StringRef RHS) const308 const char *ArgList::GetOrMakeJoinedArgString(unsigned Index,
309                                               StringRef LHS,
310                                               StringRef RHS) const {
311   StringRef Cur = getArgString(Index);
312   if (Cur.size() == LHS.size() + RHS.size() &&
313       Cur.startswith(LHS) && Cur.endswith(RHS))
314     return Cur.data();
315 
316   return MakeArgString(LHS + RHS);
317 }
318 
319 //
320 
InputArgList(const char * const * ArgBegin,const char * const * ArgEnd)321 InputArgList::InputArgList(const char* const *ArgBegin,
322                            const char* const *ArgEnd)
323   : NumInputArgStrings(ArgEnd - ArgBegin) {
324   ArgStrings.append(ArgBegin, ArgEnd);
325 }
326 
~InputArgList()327 InputArgList::~InputArgList() {
328   // An InputArgList always owns its arguments.
329   for (iterator it = begin(), ie = end(); it != ie; ++it)
330     delete *it;
331 }
332 
MakeIndex(StringRef String0) const333 unsigned InputArgList::MakeIndex(StringRef String0) const {
334   unsigned Index = ArgStrings.size();
335 
336   // Tuck away so we have a reliable const char *.
337   SynthesizedStrings.push_back(String0);
338   ArgStrings.push_back(SynthesizedStrings.back().c_str());
339 
340   return Index;
341 }
342 
MakeIndex(StringRef String0,StringRef String1) const343 unsigned InputArgList::MakeIndex(StringRef String0,
344                                  StringRef String1) const {
345   unsigned Index0 = MakeIndex(String0);
346   unsigned Index1 = MakeIndex(String1);
347   assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!");
348   (void) Index1;
349   return Index0;
350 }
351 
MakeArgStringRef(StringRef Str) const352 const char *InputArgList::MakeArgStringRef(StringRef Str) const {
353   return getArgString(MakeIndex(Str));
354 }
355 
356 //
357 
DerivedArgList(const InputArgList & BaseArgs)358 DerivedArgList::DerivedArgList(const InputArgList &BaseArgs)
359     : BaseArgs(BaseArgs) {}
360 
~DerivedArgList()361 DerivedArgList::~DerivedArgList() {}
362 
MakeArgStringRef(StringRef Str) const363 const char *DerivedArgList::MakeArgStringRef(StringRef Str) const {
364   return BaseArgs.MakeArgString(Str);
365 }
366 
AddSynthesizedArg(Arg * A)367 void DerivedArgList::AddSynthesizedArg(Arg *A) {
368   SynthesizedArgs.push_back(std::unique_ptr<Arg>(A));
369 }
370 
MakeFlagArg(const Arg * BaseArg,const Option Opt) const371 Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option Opt) const {
372   SynthesizedArgs.push_back(
373       make_unique<Arg>(Opt, MakeArgString(Opt.getPrefix() + Opt.getName()),
374                        BaseArgs.MakeIndex(Opt.getName()), BaseArg));
375   return SynthesizedArgs.back().get();
376 }
377 
MakePositionalArg(const Arg * BaseArg,const Option Opt,StringRef Value) const378 Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option Opt,
379                                        StringRef Value) const {
380   unsigned Index = BaseArgs.MakeIndex(Value);
381   SynthesizedArgs.push_back(
382       make_unique<Arg>(Opt, MakeArgString(Opt.getPrefix() + Opt.getName()),
383                        Index, BaseArgs.getArgString(Index), BaseArg));
384   return SynthesizedArgs.back().get();
385 }
386 
MakeSeparateArg(const Arg * BaseArg,const Option Opt,StringRef Value) const387 Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option Opt,
388                                      StringRef Value) const {
389   unsigned Index = BaseArgs.MakeIndex(Opt.getName(), Value);
390   SynthesizedArgs.push_back(
391       make_unique<Arg>(Opt, MakeArgString(Opt.getPrefix() + Opt.getName()),
392                        Index, BaseArgs.getArgString(Index + 1), BaseArg));
393   return SynthesizedArgs.back().get();
394 }
395 
MakeJoinedArg(const Arg * BaseArg,const Option Opt,StringRef Value) const396 Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option Opt,
397                                    StringRef Value) const {
398   unsigned Index = BaseArgs.MakeIndex((Opt.getName() + Value).str());
399   SynthesizedArgs.push_back(make_unique<Arg>(
400       Opt, MakeArgString(Opt.getPrefix() + Opt.getName()), Index,
401       BaseArgs.getArgString(Index) + Opt.getName().size(), BaseArg));
402   return SynthesizedArgs.back().get();
403 }
404