[cfe-commits] r108672 - in /cfe/trunk: test/Driver/at_file.c test/Driver/at_file.c.args tools/driver/driver.cpp

Rafael Espindola rafael.espindola at gmail.com
Sun Jul 18 20:08:01 PDT 2010


Author: rafael
Date: Sun Jul 18 22:08:01 2010
New Revision: 108672

URL: http://llvm.org/viewvc/llvm-project?rev=108672&view=rev
Log:
Implement support for reading arguments specified in a file with @file.

Added:
    cfe/trunk/test/Driver/at_file.c
    cfe/trunk/test/Driver/at_file.c.args
Modified:
    cfe/trunk/tools/driver/driver.cpp

Added: cfe/trunk/test/Driver/at_file.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/at_file.c?rev=108672&view=auto
==============================================================================
--- cfe/trunk/test/Driver/at_file.c (added)
+++ cfe/trunk/test/Driver/at_file.c Sun Jul 18 22:08:01 2010
@@ -0,0 +1,30 @@
+// RUN: %clang -E %s @%s.args -o %t.log
+// RUN: FileCheck --input-file=%t.log %s
+
+// CHECK: bar1
+// CHECK-NEXT: bar2 zed2
+// CHECK-NEXT: bar3 zed3
+// CHECK-NEXT: bar4 zed4
+// CHECK-NEXT: bar5 zed5
+// CHECK-NEXT: 'bar6 zed6'
+// CHECK-NEXT: "bar7 zed7"
+// CHECK-NEXT: foo8bar8zed8
+// CHECK-NEXT: foo9'bar9'zed9
+// CHECK-NEXT: foo10"bar10"zed10
+// CHECK: bar
+// CHECK: zed12
+
+foo1
+foo2
+foo3
+foo4
+foo5
+foo6
+foo7
+foo8
+foo9
+foo10
+#ifdef foo11
+bar
+#endif
+foo12

Added: cfe/trunk/test/Driver/at_file.c.args
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/at_file.c.args?rev=108672&view=auto
==============================================================================
--- cfe/trunk/test/Driver/at_file.c.args (added)
+++ cfe/trunk/test/Driver/at_file.c.args Sun Jul 18 22:08:01 2010
@@ -0,0 +1,11 @@
+-Dfoo1=bar1 -Dfoo2="bar2 zed2"
+-Dfoo3='bar3 zed3'
+"-Dfoo4=bar4 zed4"
+'-Dfoo5=bar5 zed5'
+-Dfoo6="'bar6 zed6'"
+-Dfoo7='"bar7 zed7"'
+-Dfoo8=foo8"bar8"zed8
+-Dfoo9=foo9\'bar9\'zed9
+-Dfoo10=foo10\"bar10\"zed10
+-D foo11
+-Dfoo12=zed12\

Modified: cfe/trunk/tools/driver/driver.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/driver/driver.cpp?rev=108672&r1=108671&r2=108672&view=diff
==============================================================================
--- cfe/trunk/tools/driver/driver.cpp (original)
+++ cfe/trunk/tools/driver/driver.cpp Sun Jul 18 22:08:01 2010
@@ -19,9 +19,12 @@
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/Config/config.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/Timer.h"
@@ -173,19 +176,107 @@
 extern int cc1as_main(const char **ArgBegin, const char **ArgEnd,
                       const char *Argv0, void *MainAddr);
 
-int main(int argc, const char **argv) {
+static bool ExpandArgsFromBuf(const char *FName,
+                              std::vector<const char*> &ArgVector,
+                              std::set<std::string> &SavedStrings) {
+  llvm::MemoryBuffer *MemBuf = llvm::MemoryBuffer::getFile(FName);
+  if (!MemBuf) {
+    llvm::report_fatal_error(std::string("error: could not open file ") +
+                             FName + "\n");
+    return true;
+  }
+
+  const char *Buf = MemBuf->getBufferStart();
+  char InQuote = ' ';
+  std::string CurArg;
+
+  for (const char *P = Buf; ; ++P) {
+    if (*P == '\0' || (isspace(*P) && InQuote == ' ')) {
+      if (!CurArg.empty()) {
+
+        if (CurArg[0] != '@') {
+          ArgVector.push_back(SaveStringInSet(SavedStrings, CurArg));
+        } else {
+          const char *NestedName = &CurArg[1];
+          if (ExpandArgsFromBuf(NestedName, ArgVector, SavedStrings)) {
+            delete MemBuf;
+            return true;
+          }
+        }
+
+        CurArg = "";
+      }
+      if (*P == '\0')
+        break;
+      else
+        continue;
+    }
+
+    if (isspace(*P)) {
+      if (InQuote != ' ')
+        CurArg.push_back(*P);
+      continue;
+    }
+
+    if (*P == '"' || *P == '\'') {
+      if (InQuote == *P)
+        InQuote = ' ';
+      else if (InQuote == ' ')
+        InQuote = *P;
+      else
+        CurArg.push_back(*P);
+      continue;
+    }
+
+    if (*P == '\\') {
+      ++P;
+      if (*P != '\0')
+        CurArg.push_back(*P);
+      continue;
+    }
+    CurArg.push_back(*P);
+  }
+  delete MemBuf;
+  return false;
+}
+
+static bool ExpandArgv(int argc, const char **argv,
+                       std::vector<const char*> &ArgVector,
+                       std::set<std::string> &SavedStrings) {
+  for (int i = 0; i < argc; ++i) {
+    const char *Arg = argv[i];
+    if (Arg[0] != '@') {
+      ArgVector.push_back(SaveStringInSet(SavedStrings, std::string(Arg)));
+      continue;
+    }
+
+    const char *FName = Arg + 1;
+    if (ExpandArgsFromBuf(FName, ArgVector, SavedStrings))
+      return false;
+  }
+  return false;
+}
+
+int main(int argc_, const char **argv_) {
   llvm::sys::PrintStackTraceOnErrorSignal();
-  llvm::PrettyStackTraceProgram X(argc, argv);
+  llvm::PrettyStackTraceProgram X(argc_, argv_);
+
+  std::set<std::string> SavedStrings;
+  std::vector<const char*> argv;
+
+  bool ret = ExpandArgv(argc_, argv_, argv, SavedStrings);
+  if (ret)
+    return 1;
 
   // Handle -cc1 integrated tools.
-  if (argc > 1 && llvm::StringRef(argv[1]).startswith("-cc1")) {
+  if (argv.size() > 1 && llvm::StringRef(argv[1]).startswith("-cc1")) {
     llvm::StringRef Tool = argv[1] + 4;
 
     if (Tool == "")
-      return cc1_main(argv+2, argv+argc, argv[0],
+      return cc1_main(&argv[2], &argv[argv.size()], argv[0],
                       (void*) (intptr_t) GetExecutablePath);
     if (Tool == "as")
-      return cc1as_main(argv+2, argv+argc, argv[0],
+      return cc1as_main(&argv[2], &argv[argv.size()], argv[0],
                       (void*) (intptr_t) GetExecutablePath);
 
     // Reject unknown tools.
@@ -194,7 +285,7 @@
   }
 
   bool CanonicalPrefixes = true;
-  for (int i = 1; i < argc; ++i) {
+  for (int i = 1, size = argv.size(); i < size; ++i) {
     if (llvm::StringRef(argv[i]) == "-no-canonical-prefixes") {
       CanonicalPrefixes = false;
       break;
@@ -230,7 +321,8 @@
   // being a symlink.
   //
   // We use *argv instead of argv[0] to work around a bogus g++ warning.
-  std::string ProgName(llvm::sys::Path(*argv).getBasename());
+  const char *progname = argv_[0];
+  std::string ProgName(llvm::sys::Path(progname).getBasename());
   if (llvm::StringRef(ProgName).endswith("++") ||
       llvm::StringRef(ProgName).rsplit('-').first.endswith("++")) {
     TheDriver.CCCIsCXX = true;
@@ -246,34 +338,30 @@
 
   // Handle QA_OVERRIDE_GCC3_OPTIONS and CCC_ADD_ARGS, used for editing a
   // command line behind the scenes.
-  std::set<std::string> SavedStrings;
-  std::vector<const char*> StringPointers(argv, argv + argc);
   if (const char *OverrideStr = ::getenv("QA_OVERRIDE_GCC3_OPTIONS")) {
     // FIXME: Driver shouldn't take extra initial argument.
-    ApplyQAOverride(StringPointers, OverrideStr, SavedStrings);
+    ApplyQAOverride(argv, OverrideStr, SavedStrings);
   } else if (const char *Cur = ::getenv("CCC_ADD_ARGS")) {
     // FIXME: Driver shouldn't take extra initial argument.
-    StringPointers.clear();
-    StringPointers.push_back(argv[0]);
+    std::vector<const char*> ExtraArgs;
 
     for (;;) {
       const char *Next = strchr(Cur, ',');
 
       if (Next) {
-        StringPointers.push_back(SaveStringInSet(SavedStrings,
-                                                 std::string(Cur, Next)));
+        ExtraArgs.push_back(SaveStringInSet(SavedStrings,
+                                            std::string(Cur, Next)));
         Cur = Next + 1;
       } else {
         if (*Cur != '\0')
-          StringPointers.push_back(SaveStringInSet(SavedStrings, Cur));
+          ExtraArgs.push_back(SaveStringInSet(SavedStrings, Cur));
         break;
       }
     }
 
-    StringPointers.insert(StringPointers.end(), argv + 1, argv + argc);
+    argv.insert(++argv.begin(), ExtraArgs.begin(), ExtraArgs.end());
   }
-  C.reset(TheDriver.BuildCompilation(StringPointers.size(),
-                                     &StringPointers[0]));
+  C.reset(TheDriver.BuildCompilation(argv.size(), &argv[0]));
 
   int Res = 0;
   if (C.get())





More information about the cfe-commits mailing list