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