summaryrefslogtreecommitdiffstats
path: root/src/depfile_parser.cc
diff options
context:
space:
mode:
authorEvan Martin <martine@danga.com>2011-12-27 23:45:30 (GMT)
committerEvan Martin <martine@danga.com>2011-12-28 02:07:53 (GMT)
commitea9746f7fe85320d3fb55aa7f3f8422e048b19fb (patch)
tree1afd9d72d89c0f9671ccfc1a9859c68596365f52 /src/depfile_parser.cc
parent3abfcdc5b02602091a54a79b3acff2462225f8b9 (diff)
downloadNinja-ea9746f7fe85320d3fb55aa7f3f8422e048b19fb.zip
Ninja-ea9746f7fe85320d3fb55aa7f3f8422e048b19fb.tar.gz
Ninja-ea9746f7fe85320d3fb55aa7f3f8422e048b19fb.tar.bz2
de-escape backslashes in depfiles while parsing
Diffstat (limited to 'src/depfile_parser.cc')
-rw-r--r--src/depfile_parser.cc193
1 files changed, 113 insertions, 80 deletions
diff --git a/src/depfile_parser.cc b/src/depfile_parser.cc
index b547661..832ad65 100644
--- a/src/depfile_parser.cc
+++ b/src/depfile_parser.cc
@@ -24,34 +24,45 @@
// How do you end a line with a backslash? The netbsd Make docs suggest
// reading the result of a shell command echoing a backslash!
//
-// Rather than implement the above, we do the simpler thing here.
+// Rather than implement all of above, we do a simpler thing here:
+// Backslashes escape a set of characters (see "escapes" defined below),
+// otherwise they are passed through verbatim.
// If anyone actually has depfiles that rely on the more complicated
// behavior we can adjust this.
bool DepfileParser::Parse(string* content, string* err) {
- char* p = &(*content)[0];
- char* end = p + content->size();
- for (;;) {
- const char* start = p;
- char yych;
-
+ // in: current parser input point.
+ // end: end of input.
+ char* in = &(*content)[0];
+ char* end = in + content->size();
+ while (in < end) {
+ // out: current output point (typically same as in, but can fall behind
+ // as we de-escape backslashes).
+ char* out = in;
+ // filename: start of the current parsed filename.
+ char* filename = out;
+ for (;;) {
+ // start: beginning of the current parsed span.
+ const char* start = in;
+ char yych;
+
{
static const unsigned char yybm[] = {
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 128, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 128, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 0, 0, 0, 0, 0,
- 0, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 0, 64, 0, 0, 64,
- 0, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 0, 0, 0, 0, 0,
+ 0, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 0, 0, 0, 0, 128,
+ 0, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -70,86 +81,108 @@ bool DepfileParser::Parse(string* content, string* err) {
0, 0, 0, 0, 0, 0, 0, 0,
};
- if ((end - p) < 2) break;
- yych = *p;
- if (yych <= '@') {
+ yych = *in;
+ if (yych <= '[') {
+ if (yych <= ':') {
+ if (yych <= '*') goto yy6;
+ goto yy4;
+ } else {
+ if (yych <= '@') goto yy6;
+ if (yych <= 'Z') goto yy4;
+ goto yy6;
+ }
+ } else {
+ if (yych <= '_') {
+ if (yych <= '\\') goto yy2;
+ if (yych <= '^') goto yy6;
+ goto yy4;
+ } else {
+ if (yych <= '`') goto yy6;
+ if (yych <= 'z') goto yy4;
+ goto yy6;
+ }
+ }
+yy2:
+ ++in;
+ if ((yych = *in) <= '$') {
if (yych <= 0x1F) {
- if (yych == '\n') goto yy4;
- goto yy7;
+ if (yych != '\n') goto yy9;
} else {
- if (yych <= ' ') goto yy4;
- if (yych <= '*') goto yy7;
- if (yych <= ':') goto yy6;
- goto yy7;
+ if (yych <= ' ') goto yy11;
+ if (yych <= '"') goto yy9;
+ goto yy11;
}
} else {
- if (yych <= '^') {
- if (yych <= 'Z') goto yy6;
- if (yych != '\\') goto yy7;
+ if (yych <= 'Z') {
+ if (yych == '*') goto yy11;
+ goto yy9;
} else {
- if (yych == '`') goto yy7;
- if (yych <= 'z') goto yy6;
- goto yy7;
+ if (yych <= '\\') goto yy11;
+ if (yych == '|') goto yy11;
+ goto yy9;
}
}
- ++p;
- if ((yych = *p) == '\n') goto yy13;
- goto yy10;
yy3:
{
- // Got a filename.
- int len = p - start;
- if (start[len - 1] == ':')
- len--; // Strip off trailing colon, if any.
-
- if (len == 0)
- continue; // Drop isolated colons.
-
- if (!out_.str_) {
- out_ = StringPiece(start, len);
- } else {
- ins_.push_back(StringPiece(start, len));
+ // For any other character (e.g. whitespace), swallow it here,
+ // allowing the outer logic to loop around again.
+ break;
}
- continue;
- }
yy4:
- ++p;
- yych = *p;
- goto yy12;
+ ++in;
+ yych = *in;
+ goto yy8;
yy5:
- { continue; }
-yy6:
- yych = *++p;
- goto yy10;
-yy7:
- ++p;
{
- *err = "BUG: depfile lexer encountered unknown state";
- return false;
- }
-yy9:
- ++p;
- if (end <= p) break;
- yych = *p;
-yy10:
- if (yybm[0+yych] & 64) {
- goto yy9;
+ // Got a span of plain text. Copy it to out if necessary.
+ int len = in - start;
+ if (out < start)
+ memmove(out, start, len);
+ out += len;
+ continue;
}
+yy6:
+ yych = *++in;
goto yy3;
-yy11:
- ++p;
- if (end <= p) break;
- yych = *p;
-yy12:
+yy7:
+ ++in;
+ yych = *in;
+yy8:
if (yybm[0+yych] & 128) {
- goto yy11;
+ goto yy7;
}
goto yy5;
-yy13:
- ++p;
- { continue; }
+yy9:
+ ++in;
+ {
+ // Let backslash before other characters through verbatim.
+ *out++ = '\\';
+ *out++ = yych;
+ continue;
+ }
+yy11:
+ ++in;
+ {
+ // De-escape backslashed character.
+ *out++ = yych;
+ continue;
+ }
+ }
+
}
+ int len = out - filename;
+ if (len > 0 && filename[len - 1] == ':')
+ len--; // Strip off trailing colon, if any.
+
+ if (len == 0)
+ continue;
+
+ if (!out_.str_) {
+ out_ = StringPiece(filename, len);
+ } else {
+ ins_.push_back(StringPiece(filename, len));
+ }
}
return true;
}