ArgList.cpp revision 45483f7a1b3e57b4603b141bee80596b2d4dd443
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/Option.h"
13
14using namespace clang::driver;
15
16ArgList::ArgList(arglist_type &_Args) : Args(_Args) {
17}
18
19ArgList::~ArgList() {
20}
21
22void ArgList::append(Arg *A) {
23  Args.push_back(A);
24}
25
26Arg *ArgList::getLastArg(options::ID Id, bool Claim) const {
27  // FIXME: Make search efficient?
28  for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) {
29    if ((*it)->getOption().matches(Id)) {
30      if (Claim) (*it)->claim();
31      return *it;
32    }
33  }
34
35  return 0;
36}
37
38Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, bool Claim) const {
39  Arg *Res, *A0 = getLastArg(Id0, false), *A1 = getLastArg(Id1, false);
40
41  if (A0 && A1)
42    Res = A0->getIndex() > A1->getIndex() ? A0 : A1;
43  else
44    Res = A0 ? A0 : A1;
45
46  if (Claim && Res)
47    Res->claim();
48
49  return Res;
50}
51
52Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, options::ID Id2,
53                         bool Claim) const {
54  Arg *Res = 0;
55  Arg *A0 = getLastArg(Id0, false);
56  Arg *A1 = getLastArg(Id1, false);
57  Arg *A2 = getLastArg(Id2, false);
58
59  int A0Idx = A0 ? A0->getIndex() : -1;
60  int A1Idx = A1 ? A1->getIndex() : -1;
61  int A2Idx = A2 ? A2->getIndex() : -1;
62
63  if (A0Idx > A1Idx) {
64    if (A0Idx > A2Idx)
65      Res = A0;
66    else if (A2Idx != -1)
67      Res = A2;
68  } else {
69    if (A1Idx > A2Idx)
70      Res = A1;
71    else if (A2Idx != -1)
72      Res = A2;
73  }
74
75  if (Claim && Res)
76    Res->claim();
77
78  return Res;
79}
80
81bool ArgList::hasFlag(options::ID Pos, options::ID Neg, bool Default) const {
82  if (Arg *A = getLastArg(Pos, Neg))
83    return A->getOption().matches(Pos);
84  return Default;
85}
86
87void ArgList::AddLastArg(ArgStringList &Output, options::ID Id) const {
88  if (Arg *A = getLastArg(Id)) {
89    A->claim();
90    A->render(*this, Output);
91  }
92}
93
94void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0) const {
95  // FIXME: Make fast.
96  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
97    const Arg *A = *it;
98    if (A->getOption().matches(Id0)) {
99      A->claim();
100      A->render(*this, Output);
101    }
102  }
103}
104
105void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0,
106                         options::ID Id1) const {
107  // FIXME: Make fast.
108  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
109    const Arg *A = *it;
110    if (A->getOption().matches(Id0) || A->getOption().matches(Id1)) {
111      A->claim();
112      A->render(*this, Output);
113    }
114  }
115}
116
117void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0,
118                         options::ID Id1, options::ID Id2) const {
119  // FIXME: Make fast.
120  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
121    const Arg *A = *it;
122    if (A->getOption().matches(Id0) || A->getOption().matches(Id1) ||
123        A->getOption().matches(Id2)) {
124      A->claim();
125      A->render(*this, Output);
126    }
127  }
128}
129
130void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0) const {
131  // FIXME: Make fast.
132  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
133    const Arg *A = *it;
134    if (A->getOption().matches(Id0)) {
135      A->claim();
136      for (unsigned i = 0, e = A->getNumValues(); i != e; ++i)
137        Output.push_back(A->getValue(*this, i));
138    }
139  }
140}
141
142void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0,
143                              options::ID Id1) const {
144  // FIXME: Make fast.
145  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
146    const Arg *A = *it;
147    if (A->getOption().matches(Id0) || A->getOption().matches(Id1)) {
148      A->claim();
149      for (unsigned i = 0, e = A->getNumValues(); i != e; ++i)
150        Output.push_back(A->getValue(*this, i));
151    }
152  }
153}
154
155void ArgList::AddAllArgsTranslated(ArgStringList &Output, options::ID Id0,
156                                   const char *Translation,
157                                   bool Joined) const {
158  // FIXME: Make fast.
159  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
160    const Arg *A = *it;
161    if (A->getOption().matches(Id0)) {
162      A->claim();
163
164      if (Joined) {
165        std::string Value = Translation;
166        Value += A->getValue(*this, 0);
167        Output.push_back(MakeArgString(Value.c_str()));
168      } else {
169        Output.push_back(Translation);
170        Output.push_back(A->getValue(*this, 0));
171      }
172    }
173  }
174}
175
176void ArgList::ClaimAllArgs(options::ID Id0) const {
177  // FIXME: Make fast.
178  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
179    const Arg *A = *it;
180    if (A->getOption().matches(Id0))
181      A->claim();
182  }
183}
184
185//
186
187InputArgList::InputArgList(const char **ArgBegin, const char **ArgEnd)
188  : ArgList(ActualArgs), NumInputArgStrings(ArgEnd - ArgBegin)
189{
190  ArgStrings.append(ArgBegin, ArgEnd);
191}
192
193InputArgList::~InputArgList() {
194  // An InputArgList always owns its arguments.
195  for (iterator it = begin(), ie = end(); it != ie; ++it)
196    delete *it;
197}
198
199unsigned InputArgList::MakeIndex(const char *String0) const {
200  unsigned Index = ArgStrings.size();
201
202  // Tuck away so we have a reliable const char *.
203  SynthesizedStrings.push_back(String0);
204  ArgStrings.push_back(SynthesizedStrings.back().c_str());
205
206  return Index;
207}
208
209unsigned InputArgList::MakeIndex(const char *String0,
210                                 const char *String1) const {
211  unsigned Index0 = MakeIndex(String0);
212  unsigned Index1 = MakeIndex(String1);
213  assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!");
214  (void) Index1;
215  return Index0;
216}
217
218const char *InputArgList::MakeArgString(const char *Str) const {
219  return getArgString(MakeIndex(Str));
220}
221
222//
223
224DerivedArgList::DerivedArgList(InputArgList &_BaseArgs, bool _OnlyProxy)
225  : ArgList(_OnlyProxy ? _BaseArgs.getArgs() : ActualArgs),
226    BaseArgs(_BaseArgs), OnlyProxy(_OnlyProxy)
227{
228}
229
230DerivedArgList::~DerivedArgList() {
231  // We only own the arguments we explicitly synthesized.
232  for (iterator it = SynthesizedArgs.begin(), ie = SynthesizedArgs.end();
233       it != ie; ++it)
234    delete *it;
235}
236
237const char *DerivedArgList::MakeArgString(const char *Str) const {
238  return BaseArgs.MakeArgString(Str);
239}
240
241Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option *Opt) const {
242  return new FlagArg(Opt, BaseArgs.MakeIndex(Opt->getName()), BaseArg);
243}
244
245Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option *Opt,
246                                       const char *Value) const {
247  return new PositionalArg(Opt, BaseArgs.MakeIndex(Value), BaseArg);
248}
249
250Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option *Opt,
251                                     const char *Value) const {
252  return new SeparateArg(Opt, BaseArgs.MakeIndex(Opt->getName(), Value), 1,
253                         BaseArg);
254}
255
256Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option *Opt,
257                                   const char *Value) const {
258  std::string Joined(Opt->getName());
259  Joined += Value;
260  return new JoinedArg(Opt, BaseArgs.MakeIndex(Joined.c_str()), BaseArg);
261}
262