From: Daniel Dunbar Date: Thu, 5 Mar 2009 06:38:47 +0000 (+0000) Subject: Driver: Basic argument parsing. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0648262df75d97b464c2be0ed867da3615659785;p=clang Driver: Basic argument parsing. - Add Driver::ParseArgStrings. - Store values directly in CommaJoinedArg to support simple access. - Add FlagArg class. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66142 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Driver/Arg.h b/include/clang/Driver/Arg.h index b558a84b89..ba72aac719 100644 --- a/include/clang/Driver/Arg.h +++ b/include/clang/Driver/Arg.h @@ -18,6 +18,7 @@ using llvm::dyn_cast; using llvm::dyn_cast_or_null; #include "Util.h" +#include namespace clang { namespace driver { @@ -34,7 +35,8 @@ namespace driver { class Arg { public: enum ArgClass { - PositionalClass = 0, + FlagClass = 0, + PositionalClass, JoinedClass, SeparateClass, CommaJoinedClass, @@ -75,6 +77,22 @@ namespace driver { 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. class PositionalArg : public Arg { public: @@ -105,7 +123,7 @@ namespace driver { static bool classof(const Arg *A) { 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 @@ -124,7 +142,7 @@ namespace driver { static bool classof(const Arg *A) { 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 @@ -134,20 +152,20 @@ namespace driver { /// separate arguments, which allows it to be used as a generic /// mechanism for passing arguments through to tools. class CommaJoinedArg : public Arg { - unsigned NumValues; + std::vector Values; 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 unsigned getNumValues() const { return NumValues; } + virtual unsigned getNumValues() const { return Values.size(); } virtual const char *getValue(const ArgList &Args, unsigned N) const; static bool classof(const Arg *A) { 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 @@ -164,7 +182,7 @@ namespace driver { static bool classof(const Arg *A) { return A->getKind() == Arg::JoinedAndSeparateClass; } - static bool classof(const PositionalArg *) { return true; } + static bool classof(const JoinedAndSeparateArg *) { return true; } }; } // end namespace driver } // end namespace clang diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index dc8c6c3d5d..dc30367c8b 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -12,6 +12,7 @@ namespace clang { namespace driver { + class ArgList; class Compilation; class OptTable; @@ -20,6 +21,10 @@ namespace driver { class Driver { OptTable *Opts; + /// ParseArgStrings - Parse the given list of strings into an + /// ArgList. + ArgList *ParseArgStrings(const char **ArgBegin, const char **ArgEnd); + public: Driver(); ~Driver(); diff --git a/include/clang/Driver/Options.def b/include/clang/Driver/Options.def index 816678af6b..3c015622cd 100644 --- a/include/clang/Driver/Options.def +++ b/include/clang/Driver/Options.def @@ -55,3 +55,4 @@ OPTION(ArchOpt, Separate, "-arch", 0, 0, "", 0) OPTION(PassExitCodesFlag, Flag, "-pass-exit-codes", 0, 0, "", 0) OPTION(PrintFileNameOpt, Joined, "-print-file-name=", 0, 0, "", 0) +OPTION(WpOpt, CommaJoined, "-Wp,", 0, 0, "", 0) diff --git a/lib/Driver/Arg.cpp b/lib/Driver/Arg.cpp index a4581d0e9e..52437e7772 100644 --- a/lib/Driver/Arg.cpp +++ b/lib/Driver/Arg.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "clang/Driver/Arg.h" +#include "clang/Driver/ArgList.h" #include "clang/Driver/Option.h" #include "llvm/Support/raw_ostream.h" @@ -28,6 +29,7 @@ void Arg::dump() const { default: assert(0 && "Invalid kind"); #define P(N) case N: llvm::errs() << #N; break + P(FlagClass); P(PositionalClass); P(JoinedClass); P(SeparateClass); @@ -49,6 +51,19 @@ void Arg::dump() const { 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) : 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 { - assert(0 && "FIXME: Implement"); + assert(N < getNumValues() && "Invalid index."); + return Args.getArgString(getIndex()); } 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 { - 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, - unsigned _NumValues) - : Arg(CommaJoinedClass, Opt, Index), NumValues(_NumValues) { + const char *Str) + : 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 { @@ -83,7 +115,8 @@ void CommaJoinedArg::render(const ArgList &Args, ArgStringList &Output) 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) @@ -95,7 +128,8 @@ void SeparateArg::render(const ArgList &Args, ArgStringList &Output) 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) @@ -109,5 +143,6 @@ void JoinedAndSeparateArg::render(const ArgList &Args, const char *JoinedAndSeparateArg::getValue(const ArgList &Args, unsigned N) const { + assert(N < getNumValues() && "Invalid index."); assert(0 && "FIXME: Implement"); } diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index d3c959499a..541a6d8eeb 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -12,7 +12,10 @@ #include "clang/Driver/Arg.h" #include "clang/Driver/ArgList.h" #include "clang/Driver/Compilation.h" +#include "clang/Driver/Option.h" #include "clang/Driver/Options.h" + +#include "llvm/Support/raw_ostream.h" using namespace clang::driver; Driver::Driver() : Opts(new OptTable()) { @@ -23,6 +26,42 @@ Driver::~Driver() { 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) { + 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(); } diff --git a/lib/Driver/Option.cpp b/lib/Driver/Option.cpp index 43d7e9e476..73cef25a55 100644 --- a/lib/Driver/Option.cpp +++ b/lib/Driver/Option.cpp @@ -127,7 +127,7 @@ Arg *FlagOption::accept(const ArgList &Args, unsigned &Index) const { if (strlen(getName()) != strlen(Args.getArgString(Index))) return 0; - return new PositionalArg(this, Index++); + return new FlagArg(this, Index++); } 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. // FIXME: Avoid strlen, and move to helper method? const char *Suffix = Args.getArgString(Index) + strlen(getName()); - const char *SuffixEnd = Suffix + strlen(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); + return new CommaJoinedArg(this, Index++, Suffix); } SeparateOption::SeparateOption(options::ID ID, const char *Name,