diff options
author | Evan Martin <martine@danga.com> | 2011-12-27 23:45:30 (GMT) |
---|---|---|
committer | Evan Martin <martine@danga.com> | 2011-12-28 02:07:53 (GMT) |
commit | ea9746f7fe85320d3fb55aa7f3f8422e048b19fb (patch) | |
tree | 1afd9d72d89c0f9671ccfc1a9859c68596365f52 /src/depfile_parser.in.cc | |
parent | 3abfcdc5b02602091a54a79b3acff2462225f8b9 (diff) | |
download | Ninja-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.cc | 96 |
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; } |