summaryrefslogtreecommitdiffstats
path: root/src/depfile_parser.in.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.in.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.in.cc')
-rw-r--r--src/depfile_parser.in.cc96
1 files changed, 62 insertions, 34 deletions
diff --git a/src/depfile_parser.in.cc b/src/depfile_parser.in.cc
index 7ac95c6..c469a2c 100644
--- a/src/depfile_parser.in.cc
+++ b/src/depfile_parser.in.cc
@@ -23,51 +23,79 @@
// 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;
- /*!re2c
- re2c:define:YYCTYPE = "char";
- re2c:define:YYCURSOR = p;
- re2c:define:YYLIMIT = end;
+ // 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;
+ /*!re2c
+ re2c:define:YYCTYPE = "char";
+ re2c:define:YYCURSOR = in;
+ re2c:define:YYLIMIT = end;
- re2c:yyfill:parameter = 0;
- re2c:define:YYFILL = break;
+ re2c:yyfill:enable = 0;
- re2c:indent:top = 2;
- re2c:indent:string = " ";
+ re2c:indent:top = 2;
+ re2c:indent:string = " ";
- re2c:yych:emit = 0;
+ re2c:yych:emit = 0;
- '\\\n' { continue; }
- [ \n]+ { continue; }
- [a-zA-Z0-9+,/\\_:.-]+ {
- // Got a filename.
- int len = p - start;
- if (start[len - 1] == ':')
- len--; // Strip off trailing colon, if any.
+ escape = [ \\#*$[|];
- if (len == 0)
- continue; // Drop isolated colons.
-
- if (!out_.str_) {
- out_ = StringPiece(start, len);
- } else {
- ins_.push_back(StringPiece(start, len));
+ '\\' escape {
+ // De-escape backslashed character.
+ *out++ = yych;
+ continue;
}
- continue;
+ '\\'. {
+ // Let backslash before other characters through verbatim.
+ *out++ = '\\';
+ *out++ = yych;
+ continue;
+ }
+ [a-zA-Z0-9+,/_:.-]+ {
+ // 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;
+ }
+ [^] {
+ // For any other character (e.g. whitespace), swallow it here,
+ // allowing the outer logic to loop around again.
+ break;
+ }
+ */
}
- [^] {
- *err = "BUG: depfile lexer encountered unknown state";
- return false;
+
+ 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;
}