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
209249259SdimStringRef ArgList::getLastArgValue(OptSpecifier Id,
210249259Sdim                                         StringRef Default) const {
211249259Sdim  if (Arg *A = getLastArg(Id))
212249259Sdim    return A->getValue();
213249259Sdim  return Default;
214249259Sdim}
215249259Sdim
216249259Sdimstd::vector<std::string> ArgList::getAllArgValues(OptSpecifier Id) const {
217249259Sdim  SmallVector<const char *, 16> Values;
218249259Sdim  AddAllArgValues(Values, Id);
219249259Sdim  return std::vector<std::string>(Values.begin(), Values.end());
220249259Sdim}
221249259Sdim
222249259Sdimvoid ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const {
223249259Sdim  if (Arg *A = getLastArg(Id)) {
224249259Sdim    A->claim();
225249259Sdim    A->render(*this, Output);
226249259Sdim  }
227249259Sdim}
228249259Sdim
229249259Sdimvoid ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
230249259Sdim                         OptSpecifier Id1, OptSpecifier Id2) const {
231249259Sdim  for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
232249259Sdim         ie = filtered_end(); it != ie; ++it) {
233249259Sdim    (*it)->claim();
234249259Sdim    (*it)->render(*this, Output);
235249259Sdim  }
236249259Sdim}
237249259Sdim
238249259Sdimvoid ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
239249259Sdim                              OptSpecifier Id1, OptSpecifier Id2) const {
240249259Sdim  for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
241249259Sdim         ie = filtered_end(); it != ie; ++it) {
242249259Sdim    (*it)->claim();
243249259Sdim    for (unsigned i = 0, e = (*it)->getNumValues(); i != e; ++i)
244249259Sdim      Output.push_back((*it)->getValue(i));
245249259Sdim  }
246249259Sdim}
247249259Sdim
248249259Sdimvoid ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
249249259Sdim                                   const char *Translation,
250249259Sdim                                   bool Joined) const {
251249259Sdim  for (arg_iterator it = filtered_begin(Id0),
252249259Sdim         ie = filtered_end(); it != ie; ++it) {
253249259Sdim    (*it)->claim();
254249259Sdim
255249259Sdim    if (Joined) {
256249259Sdim      Output.push_back(MakeArgString(StringRef(Translation) +
257249259Sdim                                     (*it)->getValue(0)));
258249259Sdim    } else {
259249259Sdim      Output.push_back(Translation);
260249259Sdim      Output.push_back((*it)->getValue(0));
261249259Sdim    }
262249259Sdim  }
263249259Sdim}
264249259Sdim
265249259Sdimvoid ArgList::ClaimAllArgs(OptSpecifier Id0) const {
266249259Sdim  for (arg_iterator it = filtered_begin(Id0),
267249259Sdim         ie = filtered_end(); it != ie; ++it)
268249259Sdim    (*it)->claim();
269249259Sdim}
270249259Sdim
271249259Sdimvoid ArgList::ClaimAllArgs() const {
272249259Sdim  for (const_iterator it = begin(), ie = end(); it != ie; ++it)
273249259Sdim    if (!(*it)->isClaimed())
274249259Sdim      (*it)->claim();
275249259Sdim}
276249259Sdim
277249259Sdimconst char *ArgList::MakeArgString(const Twine &T) const {
278249259Sdim  SmallString<256> Str;
279249259Sdim  T.toVector(Str);
280249259Sdim  return MakeArgString(Str.str());
281249259Sdim}
282249259Sdim
283249259Sdimconst char *ArgList::GetOrMakeJoinedArgString(unsigned Index,
284249259Sdim                                              StringRef LHS,
285249259Sdim                                              StringRef RHS) const {
286249259Sdim  StringRef Cur = getArgString(Index);
287249259Sdim  if (Cur.size() == LHS.size() + RHS.size() &&
288249259Sdim      Cur.startswith(LHS) && Cur.endswith(RHS))
289249259Sdim    return Cur.data();
290249259Sdim
291249259Sdim  return MakeArgString(LHS + RHS);
292249259Sdim}
293249259Sdim
294249259Sdim//
295249259Sdim
296249259SdimInputArgList::InputArgList(const char* const *ArgBegin,
297249259Sdim                           const char* const *ArgEnd)
298249259Sdim  : NumInputArgStrings(ArgEnd - ArgBegin) {
299249259Sdim  ArgStrings.append(ArgBegin, ArgEnd);
300249259Sdim}
301249259Sdim
302249259SdimInputArgList::~InputArgList() {
303249259Sdim  // An InputArgList always owns its arguments.
304249259Sdim  for (iterator it = begin(), ie = end(); it != ie; ++it)
305249259Sdim    delete *it;
306249259Sdim}
307249259Sdim
308249259Sdimunsigned InputArgList::MakeIndex(StringRef String0) const {
309249259Sdim  unsigned Index = ArgStrings.size();
310249259Sdim
311249259Sdim  // Tuck away so we have a reliable const char *.
312249259Sdim  SynthesizedStrings.push_back(String0);
313249259Sdim  ArgStrings.push_back(SynthesizedStrings.back().c_str());
314249259Sdim
315249259Sdim  return Index;
316249259Sdim}
317249259Sdim
318249259Sdimunsigned InputArgList::MakeIndex(StringRef String0,
319249259Sdim                                 StringRef String1) const {
320249259Sdim  unsigned Index0 = MakeIndex(String0);
321249259Sdim  unsigned Index1 = MakeIndex(String1);
322249259Sdim  assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!");
323249259Sdim  (void) Index1;
324249259Sdim  return Index0;
325249259Sdim}
326249259Sdim
327249259Sdimconst char *InputArgList::MakeArgString(StringRef Str) const {
328249259Sdim  return getArgString(MakeIndex(Str));
329249259Sdim}
330249259Sdim
331249259Sdim//
332249259Sdim
333249259SdimDerivedArgList::DerivedArgList(const InputArgList &_BaseArgs)
334249259Sdim  : BaseArgs(_BaseArgs) {
335249259Sdim}
336249259Sdim
337249259SdimDerivedArgList::~DerivedArgList() {
338249259Sdim  // We only own the arguments we explicitly synthesized.
339249259Sdim  for (iterator it = SynthesizedArgs.begin(), ie = SynthesizedArgs.end();
340249259Sdim       it != ie; ++it)
341249259Sdim    delete *it;
342249259Sdim}
343249259Sdim
344249259Sdimconst char *DerivedArgList::MakeArgString(StringRef Str) const {
345249259Sdim  return BaseArgs.MakeArgString(Str);
346249259Sdim}
347249259Sdim
348249259SdimArg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option Opt) const {
349249259Sdim  Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
350249259Sdim                                               Twine(Opt.getName())),
351249259Sdim                   BaseArgs.MakeIndex(Opt.getName()), BaseArg);
352249259Sdim  SynthesizedArgs.push_back(A);
353249259Sdim  return A;
354249259Sdim}
355249259Sdim
356249259SdimArg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option Opt,
357249259Sdim                                       StringRef Value) const {
358249259Sdim  unsigned Index = BaseArgs.MakeIndex(Value);
359249259Sdim  Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
360249259Sdim                                               Twine(Opt.getName())),
361249259Sdim                   Index, BaseArgs.getArgString(Index), BaseArg);
362249259Sdim  SynthesizedArgs.push_back(A);
363249259Sdim  return A;
364249259Sdim}
365249259Sdim
366249259SdimArg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option Opt,
367249259Sdim                                     StringRef Value) const {
368249259Sdim  unsigned Index = BaseArgs.MakeIndex(Opt.getName(), Value);
369249259Sdim  Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
370249259Sdim                                               Twine(Opt.getName())),
371249259Sdim                   Index, BaseArgs.getArgString(Index + 1), BaseArg);
372249259Sdim  SynthesizedArgs.push_back(A);
373249259Sdim  return A;
374249259Sdim}
375249259Sdim
376249259SdimArg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option Opt,
377249259Sdim                                   StringRef Value) const {
378249259Sdim  unsigned Index = BaseArgs.MakeIndex(Opt.getName().str() + Value.str());
379249259Sdim  Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
380249259Sdim                                               Twine(Opt.getName())), Index,
381249259Sdim                   BaseArgs.getArgString(Index) + Opt.getName().size(),
382249259Sdim                   BaseArg);
383249259Sdim  SynthesizedArgs.push_back(A);
384249259Sdim  return A;
385249259Sdim}
386