1249259Sdim//===--- ArgList.cpp - Argument List Management ---------------------------===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim
10249259Sdim#include "llvm/Option/ArgList.h"
11249259Sdim#include "llvm/ADT/SmallString.h"
12249259Sdim#include "llvm/ADT/Twine.h"
13249259Sdim#include "llvm/Option/Arg.h"
14249259Sdim#include "llvm/Option/Option.h"
15249259Sdim#include "llvm/Support/raw_ostream.h"
16249259Sdim
17249259Sdimusing namespace llvm;
18249259Sdimusing namespace llvm::opt;
19249259Sdim
20249259Sdimvoid arg_iterator::SkipToNextArg() {
21249259Sdim  for (; Current != Args.end(); ++Current) {
22249259Sdim    // Done if there are no filters.
23249259Sdim    if (!Id0.isValid())
24249259Sdim      break;
25249259Sdim
26249259Sdim    // Otherwise require a match.
27249259Sdim    const Option &O = (*Current)->getOption();
28249259Sdim    if (O.matches(Id0) ||
29249259Sdim        (Id1.isValid() && O.matches(Id1)) ||
30249259Sdim        (Id2.isValid() && O.matches(Id2)))
31249259Sdim      break;
32249259Sdim  }
33249259Sdim}
34249259Sdim
35249259Sdim//
36249259Sdim
37249259SdimArgList::ArgList() {
38249259Sdim}
39249259Sdim
40249259SdimArgList::~ArgList() {
41249259Sdim}
42249259Sdim
43249259Sdimvoid ArgList::append(Arg *A) {
44249259Sdim  Args.push_back(A);
45249259Sdim}
46249259Sdim
47249259Sdimvoid ArgList::eraseArg(OptSpecifier Id) {
48249259Sdim  for (iterator it = begin(), ie = end(); it != ie; ) {
49249259Sdim    if ((*it)->getOption().matches(Id)) {
50249259Sdim      it = Args.erase(it);
51249259Sdim      ie = end();
52249259Sdim    } else {
53249259Sdim      ++it;
54249259Sdim    }
55249259Sdim  }
56249259Sdim}
57249259Sdim
58249259SdimArg *ArgList::getLastArgNoClaim(OptSpecifier Id) const {
59249259Sdim  // FIXME: Make search efficient?
60249259Sdim  for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it)
61249259Sdim    if ((*it)->getOption().matches(Id))
62249259Sdim      return *it;
63249259Sdim  return 0;
64249259Sdim}
65249259Sdim
66249259SdimArg *ArgList::getLastArg(OptSpecifier Id) const {
67249259Sdim  Arg *Res = 0;
68249259Sdim  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
69249259Sdim    if ((*it)->getOption().matches(Id)) {
70249259Sdim      Res = *it;
71249259Sdim      Res->claim();
72249259Sdim    }
73249259Sdim  }
74249259Sdim
75249259Sdim  return Res;
76249259Sdim}
77249259Sdim
78249259SdimArg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1) const {
79249259Sdim  Arg *Res = 0;
80249259Sdim  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
81249259Sdim    if ((*it)->getOption().matches(Id0) ||
82249259Sdim        (*it)->getOption().matches(Id1)) {
83249259Sdim      Res = *it;
84249259Sdim      Res->claim();
85249259Sdim
86249259Sdim    }
87249259Sdim  }
88249259Sdim
89249259Sdim  return Res;
90249259Sdim}
91249259Sdim
92249259SdimArg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
93249259Sdim                         OptSpecifier Id2) const {
94249259Sdim  Arg *Res = 0;
95249259Sdim  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
96249259Sdim    if ((*it)->getOption().matches(Id0) ||
97249259Sdim        (*it)->getOption().matches(Id1) ||
98249259Sdim        (*it)->getOption().matches(Id2)) {
99249259Sdim      Res = *it;
100249259Sdim      Res->claim();
101249259Sdim    }
102249259Sdim  }
103249259Sdim
104249259Sdim  return Res;
105249259Sdim}
106249259Sdim
107249259SdimArg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
108249259Sdim                         OptSpecifier Id2, OptSpecifier Id3) const {
109249259Sdim  Arg *Res = 0;
110249259Sdim  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
111249259Sdim    if ((*it)->getOption().matches(Id0) ||
112249259Sdim        (*it)->getOption().matches(Id1) ||
113249259Sdim        (*it)->getOption().matches(Id2) ||
114249259Sdim        (*it)->getOption().matches(Id3)) {
115249259Sdim      Res = *it;
116249259Sdim      Res->claim();
117249259Sdim    }
118249259Sdim  }
119249259Sdim
120249259Sdim  return Res;
121249259Sdim}
122249259Sdim
123249259SdimArg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
124249259Sdim                         OptSpecifier Id2, OptSpecifier Id3,
125249259Sdim                         OptSpecifier Id4) const {
126249259Sdim  Arg *Res = 0;
127249259Sdim  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
128249259Sdim    if ((*it)->getOption().matches(Id0) ||
129249259Sdim        (*it)->getOption().matches(Id1) ||
130249259Sdim        (*it)->getOption().matches(Id2) ||
131249259Sdim        (*it)->getOption().matches(Id3) ||
132249259Sdim        (*it)->getOption().matches(Id4)) {
133249259Sdim      Res = *it;
134249259Sdim      Res->claim();
135249259Sdim    }
136249259Sdim  }
137249259Sdim
138249259Sdim  return Res;
139249259Sdim}
140249259Sdim
141249259SdimArg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
142249259Sdim                         OptSpecifier Id2, OptSpecifier Id3,
143249259Sdim                         OptSpecifier Id4, OptSpecifier Id5) const {
144249259Sdim  Arg *Res = 0;
145249259Sdim  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
146249259Sdim    if ((*it)->getOption().matches(Id0) ||
147249259Sdim        (*it)->getOption().matches(Id1) ||
148249259Sdim        (*it)->getOption().matches(Id2) ||
149249259Sdim        (*it)->getOption().matches(Id3) ||
150249259Sdim        (*it)->getOption().matches(Id4) ||
151249259Sdim        (*it)->getOption().matches(Id5)) {
152249259Sdim      Res = *it;
153249259Sdim      Res->claim();
154249259Sdim    }
155249259Sdim  }
156249259Sdim
157249259Sdim  return Res;
158249259Sdim}
159249259Sdim
160249259SdimArg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
161249259Sdim                         OptSpecifier Id2, OptSpecifier Id3,
162249259Sdim                         OptSpecifier Id4, OptSpecifier Id5,
163249259Sdim                         OptSpecifier Id6) const {
164249259Sdim  Arg *Res = 0;
165249259Sdim  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
166249259Sdim    if ((*it)->getOption().matches(Id0) ||
167249259Sdim        (*it)->getOption().matches(Id1) ||
168249259Sdim        (*it)->getOption().matches(Id2) ||
169249259Sdim        (*it)->getOption().matches(Id3) ||
170249259Sdim        (*it)->getOption().matches(Id4) ||
171249259Sdim        (*it)->getOption().matches(Id5) ||
172249259Sdim        (*it)->getOption().matches(Id6)) {
173249259Sdim      Res = *it;
174249259Sdim      Res->claim();
175249259Sdim    }
176249259Sdim  }
177249259Sdim
178249259Sdim  return Res;
179249259Sdim}
180249259Sdim
181249259SdimArg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
182249259Sdim                         OptSpecifier Id2, OptSpecifier Id3,
183249259Sdim                         OptSpecifier Id4, OptSpecifier Id5,
184249259Sdim                         OptSpecifier Id6, OptSpecifier Id7) const {
185249259Sdim  Arg *Res = 0;
186249259Sdim  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
187249259Sdim    if ((*it)->getOption().matches(Id0) ||
188249259Sdim        (*it)->getOption().matches(Id1) ||
189249259Sdim        (*it)->getOption().matches(Id2) ||
190249259Sdim        (*it)->getOption().matches(Id3) ||
191249259Sdim        (*it)->getOption().matches(Id4) ||
192249259Sdim        (*it)->getOption().matches(Id5) ||
193249259Sdim        (*it)->getOption().matches(Id6) ||
194249259Sdim        (*it)->getOption().matches(Id7)) {
195249259Sdim      Res = *it;
196249259Sdim      Res->claim();
197249259Sdim    }
198249259Sdim  }
199249259Sdim
200249259Sdim  return Res;
201249259Sdim}
202249259Sdim
203249259Sdimbool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const {
204249259Sdim  if (Arg *A = getLastArg(Pos, Neg))
205249259Sdim    return A->getOption().matches(Pos);
206249259Sdim  return Default;
207249259Sdim}
208249259Sdim
209263509Sdimbool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier PosAlias, OptSpecifier Neg,
210263509Sdim                      bool Default) const {
211263509Sdim  if (Arg *A = getLastArg(Pos, PosAlias, Neg))
212263509Sdim    return A->getOption().matches(Pos) || A->getOption().matches(PosAlias);
213263509Sdim  return Default;
214263509Sdim}
215263509Sdim
216249259SdimStringRef ArgList::getLastArgValue(OptSpecifier Id,
217249259Sdim                                         StringRef Default) const {
218249259Sdim  if (Arg *A = getLastArg(Id))
219249259Sdim    return A->getValue();
220249259Sdim  return Default;
221249259Sdim}
222249259Sdim
223249259Sdimstd::vector<std::string> ArgList::getAllArgValues(OptSpecifier Id) const {
224249259Sdim  SmallVector<const char *, 16> Values;
225249259Sdim  AddAllArgValues(Values, Id);
226249259Sdim  return std::vector<std::string>(Values.begin(), Values.end());
227249259Sdim}
228249259Sdim
229249259Sdimvoid ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const {
230249259Sdim  if (Arg *A = getLastArg(Id)) {
231249259Sdim    A->claim();
232249259Sdim    A->render(*this, Output);
233249259Sdim  }
234249259Sdim}
235249259Sdim
236263509Sdimvoid ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id0,
237263509Sdim                         OptSpecifier Id1) const {
238263509Sdim  if (Arg *A = getLastArg(Id0, Id1)) {
239263509Sdim    A->claim();
240263509Sdim    A->render(*this, Output);
241263509Sdim  }
242263509Sdim}
243263509Sdim
244249259Sdimvoid ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
245249259Sdim                         OptSpecifier Id1, OptSpecifier Id2) const {
246249259Sdim  for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
247249259Sdim         ie = filtered_end(); it != ie; ++it) {
248249259Sdim    (*it)->claim();
249249259Sdim    (*it)->render(*this, Output);
250249259Sdim  }
251249259Sdim}
252249259Sdim
253249259Sdimvoid ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
254249259Sdim                              OptSpecifier Id1, OptSpecifier Id2) const {
255249259Sdim  for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
256249259Sdim         ie = filtered_end(); it != ie; ++it) {
257249259Sdim    (*it)->claim();
258249259Sdim    for (unsigned i = 0, e = (*it)->getNumValues(); i != e; ++i)
259249259Sdim      Output.push_back((*it)->getValue(i));
260249259Sdim  }
261249259Sdim}
262249259Sdim
263249259Sdimvoid ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
264249259Sdim                                   const char *Translation,
265249259Sdim                                   bool Joined) const {
266249259Sdim  for (arg_iterator it = filtered_begin(Id0),
267249259Sdim         ie = filtered_end(); it != ie; ++it) {
268249259Sdim    (*it)->claim();
269249259Sdim
270249259Sdim    if (Joined) {
271249259Sdim      Output.push_back(MakeArgString(StringRef(Translation) +
272249259Sdim                                     (*it)->getValue(0)));
273249259Sdim    } else {
274249259Sdim      Output.push_back(Translation);
275249259Sdim      Output.push_back((*it)->getValue(0));
276249259Sdim    }
277249259Sdim  }
278249259Sdim}
279249259Sdim
280249259Sdimvoid ArgList::ClaimAllArgs(OptSpecifier Id0) const {
281249259Sdim  for (arg_iterator it = filtered_begin(Id0),
282249259Sdim         ie = filtered_end(); it != ie; ++it)
283249259Sdim    (*it)->claim();
284249259Sdim}
285249259Sdim
286249259Sdimvoid ArgList::ClaimAllArgs() const {
287249259Sdim  for (const_iterator it = begin(), ie = end(); it != ie; ++it)
288249259Sdim    if (!(*it)->isClaimed())
289249259Sdim      (*it)->claim();
290249259Sdim}
291249259Sdim
292249259Sdimconst char *ArgList::MakeArgString(const Twine &T) const {
293249259Sdim  SmallString<256> Str;
294249259Sdim  T.toVector(Str);
295249259Sdim  return MakeArgString(Str.str());
296249259Sdim}
297249259Sdim
298249259Sdimconst char *ArgList::GetOrMakeJoinedArgString(unsigned Index,
299249259Sdim                                              StringRef LHS,
300249259Sdim                                              StringRef RHS) const {
301249259Sdim  StringRef Cur = getArgString(Index);
302249259Sdim  if (Cur.size() == LHS.size() + RHS.size() &&
303249259Sdim      Cur.startswith(LHS) && Cur.endswith(RHS))
304249259Sdim    return Cur.data();
305249259Sdim
306249259Sdim  return MakeArgString(LHS + RHS);
307249259Sdim}
308249259Sdim
309249259Sdim//
310249259Sdim
311249259SdimInputArgList::InputArgList(const char* const *ArgBegin,
312249259Sdim                           const char* const *ArgEnd)
313249259Sdim  : NumInputArgStrings(ArgEnd - ArgBegin) {
314249259Sdim  ArgStrings.append(ArgBegin, ArgEnd);
315249259Sdim}
316249259Sdim
317249259SdimInputArgList::~InputArgList() {
318249259Sdim  // An InputArgList always owns its arguments.
319249259Sdim  for (iterator it = begin(), ie = end(); it != ie; ++it)
320249259Sdim    delete *it;
321249259Sdim}
322249259Sdim
323249259Sdimunsigned InputArgList::MakeIndex(StringRef String0) const {
324249259Sdim  unsigned Index = ArgStrings.size();
325249259Sdim
326249259Sdim  // Tuck away so we have a reliable const char *.
327249259Sdim  SynthesizedStrings.push_back(String0);
328249259Sdim  ArgStrings.push_back(SynthesizedStrings.back().c_str());
329249259Sdim
330249259Sdim  return Index;
331249259Sdim}
332249259Sdim
333249259Sdimunsigned InputArgList::MakeIndex(StringRef String0,
334249259Sdim                                 StringRef String1) const {
335249259Sdim  unsigned Index0 = MakeIndex(String0);
336249259Sdim  unsigned Index1 = MakeIndex(String1);
337249259Sdim  assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!");
338249259Sdim  (void) Index1;
339249259Sdim  return Index0;
340249259Sdim}
341249259Sdim
342249259Sdimconst char *InputArgList::MakeArgString(StringRef Str) const {
343249259Sdim  return getArgString(MakeIndex(Str));
344249259Sdim}
345249259Sdim
346249259Sdim//
347249259Sdim
348249259SdimDerivedArgList::DerivedArgList(const InputArgList &_BaseArgs)
349249259Sdim  : BaseArgs(_BaseArgs) {
350249259Sdim}
351249259Sdim
352249259SdimDerivedArgList::~DerivedArgList() {
353249259Sdim  // We only own the arguments we explicitly synthesized.
354249259Sdim  for (iterator it = SynthesizedArgs.begin(), ie = SynthesizedArgs.end();
355249259Sdim       it != ie; ++it)
356249259Sdim    delete *it;
357249259Sdim}
358249259Sdim
359249259Sdimconst char *DerivedArgList::MakeArgString(StringRef Str) const {
360249259Sdim  return BaseArgs.MakeArgString(Str);
361249259Sdim}
362249259Sdim
363249259SdimArg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option Opt) const {
364249259Sdim  Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
365249259Sdim                                               Twine(Opt.getName())),
366249259Sdim                   BaseArgs.MakeIndex(Opt.getName()), BaseArg);
367249259Sdim  SynthesizedArgs.push_back(A);
368249259Sdim  return A;
369249259Sdim}
370249259Sdim
371249259SdimArg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option Opt,
372249259Sdim                                       StringRef Value) const {
373249259Sdim  unsigned Index = BaseArgs.MakeIndex(Value);
374249259Sdim  Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
375249259Sdim                                               Twine(Opt.getName())),
376249259Sdim                   Index, BaseArgs.getArgString(Index), BaseArg);
377249259Sdim  SynthesizedArgs.push_back(A);
378249259Sdim  return A;
379249259Sdim}
380249259Sdim
381249259SdimArg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option Opt,
382249259Sdim                                     StringRef Value) const {
383249259Sdim  unsigned Index = BaseArgs.MakeIndex(Opt.getName(), Value);
384249259Sdim  Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
385249259Sdim                                               Twine(Opt.getName())),
386249259Sdim                   Index, BaseArgs.getArgString(Index + 1), BaseArg);
387249259Sdim  SynthesizedArgs.push_back(A);
388249259Sdim  return A;
389249259Sdim}
390249259Sdim
391249259SdimArg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option Opt,
392249259Sdim                                   StringRef Value) const {
393249259Sdim  unsigned Index = BaseArgs.MakeIndex(Opt.getName().str() + Value.str());
394249259Sdim  Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
395249259Sdim                                               Twine(Opt.getName())), Index,
396249259Sdim                   BaseArgs.getArgString(Index) + Opt.getName().size(),
397249259Sdim                   BaseArg);
398249259Sdim  SynthesizedArgs.push_back(A);
399249259Sdim  return A;
400249259Sdim}
401