Add an arg_iterator, for iterating over a subset of arguments in an ArgList.

llvm-svn: 89860
This commit is contained in:
Daniel Dunbar 2009-11-25 11:33:30 +00:00
parent b7f1babb73
commit b8c2f7d950
3 changed files with 118 additions and 77 deletions

View File

@ -25,8 +25,66 @@ namespace llvm {
namespace clang {
namespace driver {
class Arg;
class ArgList;
class Option;
/// arg_iterator - Iterates through arguments stored inside an ArgList.
class arg_iterator {
/// The current argument.
llvm::SmallVectorImpl<Arg*>::const_iterator Current;
/// The argument list we are iterating over.
const ArgList &Args;
/// Optional filters on the arguments which will be match. Most clients
/// should never want to iterate over arguments without filters, so we won't
/// bother to factor this into two separate iterator implementations.
//
// FIXME: Make efficient; the idea is to provide efficient iteration over
// all arguments which match a particular id and then just provide an
// iterator combinator which takes multiple iterators which can be
// efficiently compared and returns them in order.
OptSpecifier Id0, Id1, Id2;
void SkipToNextArg();
public:
typedef const Arg* value_type;
typedef const Arg* reference;
typedef const Arg* pointer;
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
arg_iterator(llvm::SmallVectorImpl<Arg*>::const_iterator it,
const ArgList &_Args, OptSpecifier _Id0 = 0U,
OptSpecifier _Id1 = 0U, OptSpecifier _Id2 = 0U)
: Current(it), Args(_Args), Id0(_Id0), Id1(_Id1), Id2(_Id2) {
SkipToNextArg();
}
reference operator*() const { return *Current; }
pointer operator->() const { return *Current; }
arg_iterator &operator++() {
++Current;
SkipToNextArg();
return *this;
}
arg_iterator operator++(int) {
arg_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool operator==(arg_iterator LHS, arg_iterator RHS) {
return LHS.Current == RHS.Current;
}
friend bool operator!=(arg_iterator LHS, arg_iterator RHS) {
return !(LHS == RHS);
}
};
/// ArgList - Ordered collection of driver arguments.
///
/// The ArgList class manages a list of Arg instances as well as
@ -62,6 +120,10 @@ namespace driver {
unsigned size() const { return Args.size(); }
/// @}
/// @name Arg Iteration
/// @{
iterator begin() { return Args.begin(); }
iterator end() { return Args.end(); }
@ -74,6 +136,18 @@ namespace driver {
const_reverse_iterator rbegin() const { return Args.rbegin(); }
const_reverse_iterator rend() const { return Args.rend(); }
arg_iterator filtered_begin(OptSpecifier Id0 = 0U, OptSpecifier Id1 = 0U,
OptSpecifier Id2 = 0U) const {
return arg_iterator(Args.begin(), *this, Id0, Id1, Id2);
}
arg_iterator filtered_end() const {
return arg_iterator(Args.end(), *this);
}
/// @}
/// @name Arg Access
/// @{
/// hasArg - Does the arg list contain any option matching \arg Id.
///
/// \arg Claim Whether the argument should be claimed, if it exists.
@ -115,17 +189,13 @@ namespace driver {
void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const;
/// AddAllArgs - Render all arguments matching the given ids.
void AddAllArgs(ArgStringList &Output, OptSpecifier Id0) const;
void AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
OptSpecifier Id1) const;
void AddAllArgs(ArgStringList &Output, OptSpecifier Id0, OptSpecifier Id1,
OptSpecifier Id2) const;
OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;
/// AddAllArgValues - Render the argument values of all arguments
/// matching the given ids.
void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0) const;
void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
OptSpecifier Id1) const;
OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;
/// AddAllArgsTranslated - Render all the arguments matching the
/// given ids, but forced to separate args and using the provided

View File

@ -22,9 +22,12 @@ namespace driver {
explicit OptSpecifier(bool); // DO NOT IMPLEMENT
public:
OptSpecifier() : ID(0) {}
/*implicit*/ OptSpecifier(unsigned _ID) : ID(_ID) {}
/*implicit*/ OptSpecifier(const Option *Opt);
bool isValid() const { return ID != 0; }
unsigned getID() const { return ID; }
bool operator==(OptSpecifier Opt) const { return ID == Opt.getID(); }

View File

@ -17,6 +17,23 @@
using namespace clang::driver;
void arg_iterator::SkipToNextArg() {
for (; Current != Args.end(); ++Current) {
// Done if there are no filters.
if (!Id0.isValid())
break;
// Otherwise require a match.
const Option &O = (*Current)->getOption();
if (O.matches(Id0) ||
(Id1.isValid() && O.matches(Id1)) ||
(Id2.isValid() && O.matches(Id2)))
break;
}
}
//
ArgList::ArgList(arglist_type &_Args) : Args(_Args) {
}
@ -98,95 +115,46 @@ void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const {
}
}
void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0) const {
// FIXME: Make fast.
for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
const Arg *A = *it;
if (A->getOption().matches(Id0)) {
A->claim();
A->render(*this, Output);
}
}
}
void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
OptSpecifier Id1) const {
// FIXME: Make fast.
for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
const Arg *A = *it;
if (A->getOption().matches(Id0) || A->getOption().matches(Id1)) {
A->claim();
A->render(*this, Output);
}
}
}
void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
OptSpecifier Id1, OptSpecifier Id2) const {
// FIXME: Make fast.
for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
const Arg *A = *it;
if (A->getOption().matches(Id0) || A->getOption().matches(Id1) ||
A->getOption().matches(Id2)) {
A->claim();
A->render(*this, Output);
}
}
}
void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0) const {
// FIXME: Make fast.
for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
const Arg *A = *it;
if (A->getOption().matches(Id0)) {
A->claim();
for (unsigned i = 0, e = A->getNumValues(); i != e; ++i)
Output.push_back(A->getValue(*this, i));
}
for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
ie = filtered_end(); it != ie; ++it) {
it->claim();
it->render(*this, Output);
}
}
void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
OptSpecifier Id1) const {
// FIXME: Make fast.
for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
const Arg *A = *it;
if (A->getOption().matches(Id0) || A->getOption().matches(Id1)) {
A->claim();
for (unsigned i = 0, e = A->getNumValues(); i != e; ++i)
Output.push_back(A->getValue(*this, i));
}
OptSpecifier Id1, OptSpecifier Id2) const {
for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
ie = filtered_end(); it != ie; ++it) {
it->claim();
for (unsigned i = 0, e = it->getNumValues(); i != e; ++i)
Output.push_back(it->getValue(*this, i));
}
}
void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
const char *Translation,
bool Joined) const {
// FIXME: Make fast.
for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
const Arg *A = *it;
if (A->getOption().matches(Id0)) {
A->claim();
for (arg_iterator it = filtered_begin(Id0),
ie = filtered_end(); it != ie; ++it) {
it->claim();
if (Joined) {
std::string Value = Translation;
Value += A->getValue(*this, 0);
Output.push_back(MakeArgString(Value.c_str()));
} else {
Output.push_back(Translation);
Output.push_back(A->getValue(*this, 0));
}
if (Joined) {
Output.push_back(MakeArgString(llvm::StringRef(Translation) +
it->getValue(*this, 0)));
} else {
Output.push_back(Translation);
Output.push_back(it->getValue(*this, 0));
}
}
}
void ArgList::ClaimAllArgs(OptSpecifier Id0) const {
// FIXME: Make fast.
for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
const Arg *A = *it;
if (A->getOption().matches(Id0))
A->claim();
}
for (arg_iterator it = filtered_begin(Id0),
ie = filtered_end(); it != ie; ++it)
it->claim();
}
const char *ArgList::MakeArgString(const llvm::Twine &T) const {