Hi Rafael, I discovered a problem with this approach, unfortunately. For example, it turns out this completely breaks stuff like: $ clang -Xlinker -rpath -Xlinker @rpath/foo ...
I should have thought of this sooner -- I think this is why my original plan was to handle it inside the argument parsing routines. I'm going to revert it for now until we figure out another solution. - Daniel On Sun, Jul 18, 2010 at 8:08 PM, Rafael Espindola <[email protected]> wrote: > 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()) > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
