summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/depfile_parser.cc16
-rw-r--r--src/depfile_parser.in.cc16
-rw-r--r--src/depfile_parser_test.cc17
3 files changed, 41 insertions, 8 deletions
diff --git a/src/depfile_parser.cc b/src/depfile_parser.cc
index 8f8f9fe..7219eb0 100644
--- a/src/depfile_parser.cc
+++ b/src/depfile_parser.cc
@@ -32,8 +32,10 @@
bool DepfileParser::Parse(string* content, string* err) {
// in: current parser input point.
// end: end of input.
+ // parsing_targets: whether we are parsing targets or dependencies.
char* in = &(*content)[0];
char* end = in + content->size();
+ bool parsing_targets = true;
while (in < end) {
// out: current output point (typically same as in, but can fall behind
// as we de-escape backslashes).
@@ -180,16 +182,22 @@ yy13:
}
int len = out - filename;
- if (len > 0 && filename[len - 1] == ':')
+ const bool is_target = parsing_targets;
+ if (len > 0 && filename[len - 1] == ':') {
len--; // Strip off trailing colon, if any.
+ parsing_targets = false;
+ }
if (len == 0)
continue;
- if (!out_.str_) {
- out_ = StringPiece(filename, len);
- } else {
+ if (!is_target) {
ins_.push_back(StringPiece(filename, len));
+ } else if (!out_.str_) {
+ out_ = StringPiece(filename, len);
+ } else if (out_ != StringPiece(filename, len)) {
+ *err = "depfile has multiple output paths.";
+ return false;
}
}
return true;
diff --git a/src/depfile_parser.in.cc b/src/depfile_parser.in.cc
index de1c38f..419ed8d 100644
--- a/src/depfile_parser.in.cc
+++ b/src/depfile_parser.in.cc
@@ -31,8 +31,10 @@
bool DepfileParser::Parse(string* content, string* err) {
// in: current parser input point.
// end: end of input.
+ // parsing_targets: whether we are parsing targets or dependencies.
char* in = &(*content)[0];
char* end = in + content->size();
+ bool parsing_targets = true;
while (in < end) {
// out: current output point (typically same as in, but can fall behind
// as we de-escape backslashes).
@@ -87,16 +89,22 @@ bool DepfileParser::Parse(string* content, string* err) {
}
int len = out - filename;
- if (len > 0 && filename[len - 1] == ':')
+ const bool is_target = parsing_targets;
+ if (len > 0 && filename[len - 1] == ':') {
len--; // Strip off trailing colon, if any.
+ parsing_targets = false;
+ }
if (len == 0)
continue;
- if (!out_.str_) {
- out_ = StringPiece(filename, len);
- } else {
+ if (!is_target) {
ins_.push_back(StringPiece(filename, len));
+ } else if (!out_.str_) {
+ out_ = StringPiece(filename, len);
+ } else if (out_ != StringPiece(filename, len)) {
+ *err = "depfile has multiple output paths.";
+ return false;
}
}
return true;
diff --git a/src/depfile_parser_test.cc b/src/depfile_parser_test.cc
index 43e677c..883926a 100644
--- a/src/depfile_parser_test.cc
+++ b/src/depfile_parser_test.cc
@@ -102,3 +102,20 @@ TEST_F(DepfileParserTest, Escapes) {
parser_.out_.AsString());
ASSERT_EQ(0u, parser_.ins_.size());
}
+
+TEST_F(DepfileParserTest, UnifyMultupleOutputs) {
+ // check that multiple duplicate targets are properly unified
+ string err;
+ EXPECT_TRUE(Parse("foo foo: x y z", &err));
+ ASSERT_EQ(parser_.out_.AsString(), "foo");
+ ASSERT_EQ(parser_.ins_.size(), 3);
+ EXPECT_EQ("x", parser_.ins_[0].AsString());
+ EXPECT_EQ("y", parser_.ins_[1].AsString());
+ EXPECT_EQ("z", parser_.ins_[2].AsString());
+}
+
+TEST_F(DepfileParserTest, RejectMultipleDifferentOutputs) {
+ // check that multiple different outputs are rejected by the parser
+ string err;
+ EXPECT_FALSE(Parse("foo bar: x y z", &err));
+}