forked from OSchip/llvm-project
[llvm-ar] Fix llvm-ar response file reading on Windows
Response files where not being correctly read on Windows, this change fixes the issue and adds some tests. Differential Revision: https://reviews.llvm.org/D69665
This commit is contained in:
parent
859bcf4e3b
commit
62fa3332c9
|
@ -0,0 +1,11 @@
|
|||
## Check that response files can cope with non-ascii characters.
|
||||
|
||||
# RUN: echo 'contents' > %t-£.txt
|
||||
|
||||
# RUN: rm -f %t-£.a
|
||||
# RUN: echo 'r %t-£.a %t-£.txt' > %t-replace.txt
|
||||
# RUN: llvm-ar @%t-replace.txt
|
||||
|
||||
# RUN: echo 'p %t-£.a %t-£.txt' > %t-print.txt
|
||||
# RUN: llvm-ar @%t-print.txt | FileCheck %s
|
||||
# CHECK: contents
|
|
@ -0,0 +1,34 @@
|
|||
## llvm-ar should be able to consume response files.
|
||||
|
||||
# RUN: echo 'contents' > %t.txt
|
||||
# RUN: echo 'rc %t1.a %t.txt' > %t.response1.txt
|
||||
# RUN: llvm-ar @%t.response1.txt
|
||||
# RUN: llvm-ar p %t1.a | FileCheck %s --check-prefix=CONTENTS
|
||||
|
||||
## Quotes and Spaces.
|
||||
# RUN: echo 'contents' > '%t space.txt'
|
||||
## Python is used here to ensure the quotes are written to the response file
|
||||
# RUN: %python -c "import os; open(r'%t.response2.txt', 'w').write(r'%t2.a \"%t space.txt\"'+ '\n')"
|
||||
# RUN: llvm-ar rc @%t.response2.txt
|
||||
# RUN: llvm-ar p %t2.a | FileCheck %s --check-prefix=CONTENTS
|
||||
|
||||
## Arguments after the response file.
|
||||
# RUN: echo 'rc %t3.a' > %t.response3.txt
|
||||
# RUN: llvm-ar @%t.response3.txt %t.txt
|
||||
# RUN: llvm-ar p %t3.a | FileCheck %s --check-prefix=CONTENTS
|
||||
|
||||
# CONTENTS: contents
|
||||
|
||||
## rsp-quoting
|
||||
# RUN: not llvm-ar --rsp-quoting=foobar @%t.response1.txt 2>&1 | \
|
||||
# RUN: FileCheck %s --check-prefix=ERROR
|
||||
# ERROR: Invalid response file quoting style foobar
|
||||
|
||||
# RUN: echo -e 'rc %/t.a blah\\foo' > %t-rsp.txt
|
||||
# RUN: not llvm-ar --rsp-quoting=windows @%t-rsp.txt 2>&1 | \
|
||||
# RUN: FileCheck %s --check-prefix=WIN
|
||||
# WIN: error: blah\foo: {{[Nn]}}o such file or directory
|
||||
|
||||
# RUN: not llvm-ar -rsp-quoting posix @%t-rsp.txt 2>&1 | \
|
||||
# RUN: FileCheck %s --check-prefix=POSIX
|
||||
# POSIX: error: blahfoo: {{[Nn]}}o such file or directory
|
|
@ -83,6 +83,9 @@ OPTIONS:
|
|||
=bsd - bsd
|
||||
--plugin=<string> - ignored for compatibility
|
||||
-h --help - display this help and exit
|
||||
--rsp-quoting - quoting style for response files
|
||||
=posix - posix
|
||||
=windows - windows
|
||||
--version - print the version and exit
|
||||
@<file> - read options from <file>
|
||||
|
||||
|
@ -1096,61 +1099,105 @@ static bool handleGenericOption(StringRef arg) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static int ar_main(int argc, char **argv) {
|
||||
SmallVector<const char *, 0> Argv(argv, argv + argc);
|
||||
StringSaver Saver(Alloc);
|
||||
cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Argv);
|
||||
for (size_t i = 1; i < Argv.size(); ++i) {
|
||||
StringRef Arg = Argv[i];
|
||||
const char *match = nullptr;
|
||||
auto MatchFlagWithArg = [&](const char *expected) {
|
||||
size_t len = strlen(expected);
|
||||
if (Arg == expected) {
|
||||
if (++i >= Argv.size())
|
||||
fail(std::string(expected) + " requires an argument");
|
||||
match = Argv[i];
|
||||
return true;
|
||||
}
|
||||
if (Arg.startswith(expected) && Arg.size() > len && Arg[len] == '=') {
|
||||
match = Arg.data() + len + 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
if (handleGenericOption(Argv[i]))
|
||||
return 0;
|
||||
if (Arg == "--") {
|
||||
for (; i < Argv.size(); ++i)
|
||||
PositionalArgs.push_back(Argv[i]);
|
||||
break;
|
||||
}
|
||||
if (Arg[0] == '-') {
|
||||
if (Arg.startswith("--"))
|
||||
Arg = Argv[i] + 2;
|
||||
static const char *matchFlagWithArg(StringRef Expected,
|
||||
ArrayRef<const char *>::iterator &ArgIt,
|
||||
ArrayRef<const char *> Args) {
|
||||
StringRef Arg = *ArgIt;
|
||||
|
||||
if (Arg.startswith("--"))
|
||||
Arg = Arg.substr(2);
|
||||
else if (Arg.startswith("-"))
|
||||
Arg = Arg.substr(1);
|
||||
|
||||
size_t len = Expected.size();
|
||||
if (Arg == Expected) {
|
||||
if (++ArgIt == Args.end())
|
||||
fail(std::string(Expected) + " requires an argument");
|
||||
|
||||
return *ArgIt;
|
||||
}
|
||||
if (Arg.startswith(Expected) && Arg.size() > len && Arg[len] == '=')
|
||||
return Arg.data() + len + 1;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static cl::TokenizerCallback getRspQuoting(ArrayRef<const char *> ArgsArr) {
|
||||
cl::TokenizerCallback Ret =
|
||||
Triple(sys::getProcessTriple()).getOS() == Triple::Win32
|
||||
? cl::TokenizeWindowsCommandLine
|
||||
: cl::TokenizeGNUCommandLine;
|
||||
|
||||
for (ArrayRef<const char *>::iterator ArgIt = ArgsArr.begin();
|
||||
ArgIt != ArgsArr.end(); ++ArgIt) {
|
||||
if (const char *Match = matchFlagWithArg("rsp-quoting", ArgIt, ArgsArr)) {
|
||||
StringRef MatchRef = Match;
|
||||
if (MatchRef == "posix")
|
||||
Ret = cl::TokenizeGNUCommandLine;
|
||||
else if (MatchRef == "windows")
|
||||
Ret = cl::TokenizeWindowsCommandLine;
|
||||
else
|
||||
Arg = Argv[i] + 1;
|
||||
if (Arg == "M") {
|
||||
MRI = true;
|
||||
} else if (MatchFlagWithArg("format")) {
|
||||
FormatType = StringSwitch<Format>(match)
|
||||
.Case("default", Default)
|
||||
.Case("gnu", GNU)
|
||||
.Case("darwin", DARWIN)
|
||||
.Case("bsd", BSD)
|
||||
.Default(Unknown);
|
||||
if (FormatType == Unknown)
|
||||
fail(std::string("Invalid format ") + match);
|
||||
} else if (MatchFlagWithArg("plugin")) {
|
||||
// Ignored.
|
||||
} else {
|
||||
Options += Argv[i] + 1;
|
||||
}
|
||||
} else if (Options.empty()) {
|
||||
Options += Argv[i];
|
||||
} else {
|
||||
PositionalArgs.push_back(Argv[i]);
|
||||
fail(std::string("Invalid response file quoting style ") + Match);
|
||||
}
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
static int ar_main(int argc, char **argv) {
|
||||
SmallVector<const char *, 0> Argv(argv + 1, argv + argc);
|
||||
StringSaver Saver(Alloc);
|
||||
|
||||
cl::ExpandResponseFiles(Saver, getRspQuoting(makeArrayRef(argv, argc)), Argv);
|
||||
|
||||
ArrayRef<const char *> ArgsArr = makeArrayRef(argv, argc);
|
||||
|
||||
for (ArrayRef<const char *>::iterator ArgIt = Argv.begin();
|
||||
ArgIt != Argv.end(); ++ArgIt) {
|
||||
const char *Match = nullptr;
|
||||
|
||||
if (handleGenericOption(*ArgIt))
|
||||
return 0;
|
||||
if (strcmp(*ArgIt, "--") == 0) {
|
||||
++ArgIt;
|
||||
for (; ArgIt != Argv.end(); ++ArgIt)
|
||||
PositionalArgs.push_back(*ArgIt);
|
||||
break;
|
||||
}
|
||||
|
||||
if (*ArgIt[0] != '-') {
|
||||
if (Options.empty())
|
||||
Options += *ArgIt;
|
||||
else
|
||||
PositionalArgs.push_back(*ArgIt);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(*ArgIt, "-M") == 0) {
|
||||
MRI = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
Match = matchFlagWithArg("format", ArgIt, Argv);
|
||||
if (Match) {
|
||||
FormatType = StringSwitch<Format>(Match)
|
||||
.Case("default", Default)
|
||||
.Case("gnu", GNU)
|
||||
.Case("darwin", DARWIN)
|
||||
.Case("bsd", BSD)
|
||||
.Default(Unknown);
|
||||
if (FormatType == Unknown)
|
||||
fail(std::string("Invalid format ") + Match);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (matchFlagWithArg("plugin", ArgIt, Argv) ||
|
||||
matchFlagWithArg("rsp-quoting", ArgIt, Argv))
|
||||
continue;
|
||||
|
||||
Options += *ArgIt + 1;
|
||||
}
|
||||
|
||||
ArchiveOperation Operation = parseCommandLine();
|
||||
return performOperation(Operation, nullptr);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue