}
optional<Args>
-Args::from_atfile(const std::string& filename, bool ignore_backslash)
+Args::from_atfile(const std::string& filename, AtFileFormat format)
{
std::string argtext;
try {
while (true) {
switch (*pos) {
case '\\':
- if (ignore_backslash) {
- break;
- }
pos++;
- if (*pos == '\0') {
- continue;
+ switch (format) {
+ case AtFileFormat::QuoteAny_EscapeAny:
+ if (*pos == '\0') {
+ continue;
+ }
+ break;
+ case AtFileFormat::QuoteDouble_EscapeQuoteEscape:
+ if (*pos != '"' && *pos != '\\') {
+ pos--;
+ }
+ break;
}
break;
- case '"':
case '\'':
+ if (format == AtFileFormat::QuoteDouble_EscapeQuoteEscape) {
+ break;
+ }
+ // Fall through.
+
+ case '"':
if (quoting != '\0') {
if (quoting == *pos) {
quoting = '\0';
static Args from_argv(int argc, const char* const* argv);
static Args from_string(const std::string& command);
- static nonstd::optional<Args> from_atfile(const std::string& filename,
- bool ignore_backslash = false);
+
+ enum class AtFileFormat {
+ QuoteAny_EscapeAny, // '\'' and '"' quote, '\\' escapes any character
+ QuoteDouble_EscapeQuoteEscape, // '"' quotes, '\\' escapes only '"' and '\\'
+ };
+ static nonstd::optional<Args>
+ from_atfile(const std::string& filename,
+ AtFileFormat format = AtFileFormat::QuoteAny_EscapeAny);
Args& operator=(const Args& other) = default;
Args& operator=(Args&& other) noexcept;
++argpath;
}
auto file_args =
- Args::from_atfile(argpath, ctx.config.is_compiler_group_msvc());
+ Args::from_atfile(argpath,
+ config.is_compiler_group_msvc()
+ ? Args::AtFileFormat::QuoteDouble_EscapeQuoteEscape
+ : Args::AtFileFormat::QuoteAny_EscapeAny);
if (!file_args) {
LOG("Couldn't read arg file {}", argpath);
return Statistic::bad_compiler_arguments;
CHECK(args[5] == "si'x\" th");
CHECK(args[6] == "seve\nth");
}
+
+ SUBCASE("Only escape double quote and backslash in alternate format")
+ {
+ Util::write_file("at_file", "\"\\\"\\a\\ \\\\\\ \\b\\\"\"\\");
+ args = *Args::from_atfile(
+ "at_file", Args::AtFileFormat::QuoteDouble_EscapeQuoteEscape);
+ CHECK(args.size() == 1);
+ CHECK(args[0] == "\"\\a\\ \\\\ \\b\"\\");
+ }
+
+ SUBCASE("Ignore single quote in alternate format")
+ {
+ Util::write_file("at_file", "'a b'");
+ args = *Args::from_atfile(
+ "at_file", Args::AtFileFormat::QuoteDouble_EscapeQuoteEscape);
+ CHECK(args.size() == 2);
+ CHECK(args[0] == "'a");
+ CHECK(args[1] == "b'");
+ }
}
TEST_CASE("Args copy assignment operator")