]> granicus.if.org Git - clang/commitdiff
Driver: Basic argument parsing.
authorDaniel Dunbar <daniel@zuster.org>
Thu, 5 Mar 2009 06:38:47 +0000 (06:38 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Thu, 5 Mar 2009 06:38:47 +0000 (06:38 +0000)
 - 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

include/clang/Driver/Arg.h
include/clang/Driver/Driver.h
include/clang/Driver/Options.def
lib/Driver/Arg.cpp
lib/Driver/Driver.cpp
lib/Driver/Option.cpp

index b558a84b89d616faf8daceac82d8632e62c9ed43..ba72aac719f1564f8dab0a904e17c5692eb14041 100644 (file)
@@ -18,6 +18,7 @@ using llvm::dyn_cast;
 using llvm::dyn_cast_or_null;
 
 #include "Util.h"
+#include <vector>
 
 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<std::string> 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
index dc8c6c3d5dbb2178a53c818704c488ecd1f24a87..dc30367c8b3ded5395cf3cf094bd099b8e19a3eb 100644 (file)
@@ -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();
index 816678af6ba8e79bbde2c70933c3de98cf74ac07..3c015622cdae517c084c2a973c2aa20d6d08d052 100644 (file)
@@ -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)
index a4581d0e9ec1e4b8e96db9c49c2258f97757074d..52437e7772bdda078fcc7ba41e7891379fc5ab44 100644 (file)
@@ -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");
 }
index d3c959499a13218030fb951270ba55f29286384e..541a6d8eebae29d60688a353347277041aac00ab 100644 (file)
 #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();
 }
index 43d7e9e476062c3643b43ec28c143d95423cec7f..73cef25a55d0604e5a056ecd72b83c04c8be5f07 100644 (file)
@@ -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,