Driver: Basic argument parsing.

- Add Driver::ParseArgStrings.
 - Store values directly in CommaJoinedArg to support simple access.
 - Add FlagArg class.

llvm-svn: 66142
This commit is contained in:
Daniel Dunbar 2009-03-05 06:38:47 +00:00
parent 359df7420f
commit d02cb1dc2b
6 changed files with 114 additions and 23 deletions

View File

@ -18,6 +18,7 @@ using llvm::dyn_cast;
using llvm::dyn_cast_or_null; using llvm::dyn_cast_or_null;
#include "Util.h" #include "Util.h"
#include <vector>
namespace clang { namespace clang {
namespace driver { namespace driver {
@ -34,7 +35,8 @@ namespace driver {
class Arg { class Arg {
public: public:
enum ArgClass { enum ArgClass {
PositionalClass = 0, FlagClass = 0,
PositionalClass,
JoinedClass, JoinedClass,
SeparateClass, SeparateClass,
CommaJoinedClass, CommaJoinedClass,
@ -75,6 +77,22 @@ namespace driver {
void dump() const; void dump() const;
}; };
/// FlagArg - An argument with no value.
class FlagArg : public Arg {
public:
FlagArg(const Option *Opt, unsigned Index);
virtual void render(const ArgList &Args, ArgStringList &Output) const;
virtual unsigned getNumValues() const { return 0; }
virtual const char *getValue(const ArgList &Args, unsigned N) const;
static bool classof(const Arg *A) {
return A->getKind() == Arg::FlagClass;
}
static bool classof(const FlagArg *) { return true; }
};
/// PositionalArg - A simple positional argument. /// PositionalArg - A simple positional argument.
class PositionalArg : public Arg { class PositionalArg : public Arg {
public: public:
@ -105,7 +123,7 @@ namespace driver {
static bool classof(const Arg *A) { static bool classof(const Arg *A) {
return A->getKind() == Arg::JoinedClass; return A->getKind() == Arg::JoinedClass;
} }
static bool classof(const PositionalArg *) { return true; } static bool classof(const JoinedArg *) { return true; }
}; };
/// SeparateArg - An argument where one or more values follow the /// SeparateArg - An argument where one or more values follow the
@ -124,7 +142,7 @@ namespace driver {
static bool classof(const Arg *A) { static bool classof(const Arg *A) {
return A->getKind() == Arg::SeparateClass; return A->getKind() == Arg::SeparateClass;
} }
static bool classof(const PositionalArg *) { return true; } static bool classof(const SeparateArg *) { return true; }
}; };
/// CommaJoinedArg - An argument with multiple values joined by /// CommaJoinedArg - An argument with multiple values joined by
@ -134,20 +152,20 @@ namespace driver {
/// separate arguments, which allows it to be used as a generic /// separate arguments, which allows it to be used as a generic
/// mechanism for passing arguments through to tools. /// mechanism for passing arguments through to tools.
class CommaJoinedArg : public Arg { class CommaJoinedArg : public Arg {
unsigned NumValues; std::vector<std::string> Values;
public: public:
CommaJoinedArg(const Option *Opt, unsigned Index, unsigned NumValues); CommaJoinedArg(const Option *Opt, unsigned Index, const char *Str);
virtual void render(const ArgList &Args, ArgStringList &Output) const; virtual void render(const ArgList &Args, ArgStringList &Output) const;
virtual unsigned getNumValues() const { return NumValues; } virtual unsigned getNumValues() const { return Values.size(); }
virtual const char *getValue(const ArgList &Args, unsigned N) const; virtual const char *getValue(const ArgList &Args, unsigned N) const;
static bool classof(const Arg *A) { static bool classof(const Arg *A) {
return A->getKind() == Arg::CommaJoinedClass; return A->getKind() == Arg::CommaJoinedClass;
} }
static bool classof(const PositionalArg *) { return true; } static bool classof(const CommaJoinedArg *) { return true; }
}; };
/// JoinedAndSeparateArg - An argument with both joined and separate /// JoinedAndSeparateArg - An argument with both joined and separate
@ -164,7 +182,7 @@ namespace driver {
static bool classof(const Arg *A) { static bool classof(const Arg *A) {
return A->getKind() == Arg::JoinedAndSeparateClass; return A->getKind() == Arg::JoinedAndSeparateClass;
} }
static bool classof(const PositionalArg *) { return true; } static bool classof(const JoinedAndSeparateArg *) { return true; }
}; };
} // end namespace driver } // end namespace driver
} // end namespace clang } // end namespace clang

View File

@ -12,6 +12,7 @@
namespace clang { namespace clang {
namespace driver { namespace driver {
class ArgList;
class Compilation; class Compilation;
class OptTable; class OptTable;
@ -20,6 +21,10 @@ namespace driver {
class Driver { class Driver {
OptTable *Opts; OptTable *Opts;
/// ParseArgStrings - Parse the given list of strings into an
/// ArgList.
ArgList *ParseArgStrings(const char **ArgBegin, const char **ArgEnd);
public: public:
Driver(); Driver();
~Driver(); ~Driver();

View File

@ -55,3 +55,4 @@
OPTION(ArchOpt, Separate, "-arch", 0, 0, "", 0) OPTION(ArchOpt, Separate, "-arch", 0, 0, "", 0)
OPTION(PassExitCodesFlag, Flag, "-pass-exit-codes", 0, 0, "", 0) OPTION(PassExitCodesFlag, Flag, "-pass-exit-codes", 0, 0, "", 0)
OPTION(PrintFileNameOpt, Joined, "-print-file-name=", 0, 0, "", 0) OPTION(PrintFileNameOpt, Joined, "-print-file-name=", 0, 0, "", 0)
OPTION(WpOpt, CommaJoined, "-Wp,", 0, 0, "", 0)

View File

@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "clang/Driver/Arg.h" #include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h"
#include "clang/Driver/Option.h" #include "clang/Driver/Option.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
@ -28,6 +29,7 @@ void Arg::dump() const {
default: default:
assert(0 && "Invalid kind"); assert(0 && "Invalid kind");
#define P(N) case N: llvm::errs() << #N; break #define P(N) case N: llvm::errs() << #N; break
P(FlagClass);
P(PositionalClass); P(PositionalClass);
P(JoinedClass); P(JoinedClass);
P(SeparateClass); P(SeparateClass);
@ -49,6 +51,19 @@ void Arg::dump() const {
llvm::errs().flush(); // FIXME llvm::errs().flush(); // FIXME
} }
FlagArg::FlagArg(const Option *Opt, unsigned Index)
: Arg(FlagClass, Opt, Index) {
}
void FlagArg::render(const ArgList &Args, ArgStringList &Output) const {
assert(0 && "FIXME: Implement");
}
const char *FlagArg::getValue(const ArgList &Args, unsigned N) const {
assert(0 && "Invalid index.");
return 0;
}
PositionalArg::PositionalArg(const Option *Opt, unsigned Index) PositionalArg::PositionalArg(const Option *Opt, unsigned Index)
: Arg(PositionalClass, Opt, Index) { : Arg(PositionalClass, Opt, Index) {
} }
@ -58,7 +73,8 @@ void PositionalArg::render(const ArgList &Args, ArgStringList &Output) const {
} }
const char *PositionalArg::getValue(const ArgList &Args, unsigned N) const { const char *PositionalArg::getValue(const ArgList &Args, unsigned N) const {
assert(0 && "FIXME: Implement"); assert(N < getNumValues() && "Invalid index.");
return Args.getArgString(getIndex());
} }
JoinedArg::JoinedArg(const Option *Opt, unsigned Index) JoinedArg::JoinedArg(const Option *Opt, unsigned Index)
@ -70,12 +86,28 @@ void JoinedArg::render(const ArgList &Args, ArgStringList &Output) const {
} }
const char *JoinedArg::getValue(const ArgList &Args, unsigned N) const { const char *JoinedArg::getValue(const ArgList &Args, unsigned N) const {
assert(0 && "FIXME: Implement"); assert(N < getNumValues() && "Invalid index.");
// FIXME: Avoid strlen.
return Args.getArgString(getIndex()) + strlen(getOption().getName());
} }
CommaJoinedArg::CommaJoinedArg(const Option *Opt, unsigned Index, CommaJoinedArg::CommaJoinedArg(const Option *Opt, unsigned Index,
unsigned _NumValues) const char *Str)
: Arg(CommaJoinedClass, Opt, Index), NumValues(_NumValues) { : Arg(CommaJoinedClass, Opt, Index) {
const char *Prev = Str;
for (;; ++Str) {
char c = *Str;
if (!c) {
if (Prev != Str)
Values.push_back(std::string(Prev, Str));
break;
} else if (c == ',') {
if (Prev != Str)
Values.push_back(std::string(Prev, Str));
Prev = Str + 1;
}
}
} }
void CommaJoinedArg::render(const ArgList &Args, ArgStringList &Output) const { void CommaJoinedArg::render(const ArgList &Args, ArgStringList &Output) const {
@ -83,7 +115,8 @@ void CommaJoinedArg::render(const ArgList &Args, ArgStringList &Output) const {
} }
const char *CommaJoinedArg::getValue(const ArgList &Args, unsigned N) const { const char *CommaJoinedArg::getValue(const ArgList &Args, unsigned N) const {
assert(0 && "FIXME: Implement"); assert(N < getNumValues() && "Invalid index.");
return Values[N].c_str();
} }
SeparateArg::SeparateArg(const Option *Opt, unsigned Index, unsigned _NumValues) SeparateArg::SeparateArg(const Option *Opt, unsigned Index, unsigned _NumValues)
@ -95,7 +128,8 @@ void SeparateArg::render(const ArgList &Args, ArgStringList &Output) const {
} }
const char *SeparateArg::getValue(const ArgList &Args, unsigned N) const { const char *SeparateArg::getValue(const ArgList &Args, unsigned N) const {
assert(0 && "FIXME: Implement"); assert(N < getNumValues() && "Invalid index.");
return Args.getArgString(getIndex() + 1 + N);
} }
JoinedAndSeparateArg::JoinedAndSeparateArg(const Option *Opt, unsigned Index) JoinedAndSeparateArg::JoinedAndSeparateArg(const Option *Opt, unsigned Index)
@ -109,5 +143,6 @@ void JoinedAndSeparateArg::render(const ArgList &Args,
const char *JoinedAndSeparateArg::getValue(const ArgList &Args, const char *JoinedAndSeparateArg::getValue(const ArgList &Args,
unsigned N) const { unsigned N) const {
assert(N < getNumValues() && "Invalid index.");
assert(0 && "FIXME: Implement"); assert(0 && "FIXME: Implement");
} }

View File

@ -12,7 +12,10 @@
#include "clang/Driver/Arg.h" #include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h" #include "clang/Driver/ArgList.h"
#include "clang/Driver/Compilation.h" #include "clang/Driver/Compilation.h"
#include "clang/Driver/Option.h"
#include "clang/Driver/Options.h" #include "clang/Driver/Options.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang::driver; using namespace clang::driver;
Driver::Driver() : Opts(new OptTable()) { Driver::Driver() : Opts(new OptTable()) {
@ -23,6 +26,42 @@ Driver::~Driver() {
delete Opts; delete Opts;
} }
ArgList *Driver::ParseArgStrings(const char **ArgBegin, const char **ArgEnd) {
ArgList *Args = new ArgList(ArgBegin, ArgEnd);
unsigned Index = 0, End = ArgEnd - ArgBegin;
while (Index < End) {
unsigned Prev = Index;
Arg *A = getOpts().ParseOneArg(*Args, Index, End);
if (A)
Args->append(A);
assert(Index > Prev && "Parser failed to consume argument.");
}
return Args;
}
Compilation *Driver::BuildCompilation(int argc, const char **argv) { Compilation *Driver::BuildCompilation(int argc, const char **argv) {
ArgList *Args = ParseArgStrings(argv + 1, argv + argc);
// Hard coded to print-options behavior.
unsigned i = 0;
for (ArgList::iterator it = Args->begin(), ie = Args->end();
it != ie; ++it, ++i) {
Arg *A = *it;
llvm::errs() << "Option " << i << " - "
<< "Name: \"" << A->getOption().getName() << "\", "
<< "Values: {";
for (unsigned j = 0; j < A->getNumValues(); ++j) {
if (j)
llvm::errs() << ", ";
llvm::errs() << '"' << A->getValue(*Args, j) << '"';
}
llvm::errs() << "}\n";
llvm::errs().flush(); // FIXME
}
return new Compilation(); return new Compilation();
} }

View File

@ -127,7 +127,7 @@ Arg *FlagOption::accept(const ArgList &Args, unsigned &Index) const {
if (strlen(getName()) != strlen(Args.getArgString(Index))) if (strlen(getName()) != strlen(Args.getArgString(Index)))
return 0; return 0;
return new PositionalArg(this, Index++); return new FlagArg(this, Index++);
} }
JoinedOption::JoinedOption(options::ID ID, const char *Name, JoinedOption::JoinedOption(options::ID ID, const char *Name,
@ -153,14 +153,7 @@ Arg *CommaJoinedOption::accept(const ArgList &Args, unsigned &Index) const {
// Get the suffix string. // Get the suffix string.
// FIXME: Avoid strlen, and move to helper method? // FIXME: Avoid strlen, and move to helper method?
const char *Suffix = Args.getArgString(Index) + strlen(getName()); const char *Suffix = Args.getArgString(Index) + strlen(getName());
const char *SuffixEnd = Suffix + strlen(Suffix); return new CommaJoinedArg(this, Index++, Suffix);
// Degenerate case, exact match has no values.
if (Suffix == SuffixEnd)
return new CommaJoinedArg(this, Index++, 0);
return new CommaJoinedArg(this, Index++,
std::count(Suffix, SuffixEnd, ',') + 1);
} }
SeparateOption::SeparateOption(options::ID ID, const char *Name, SeparateOption::SeparateOption(options::ID ID, const char *Name,