From bbf180d581ada47011c66c735bffdd87cddd0bd1 Mon Sep 17 00:00:00 2001 From: Evan Martin Date: Mon, 19 Dec 2011 11:14:35 -0800 Subject: [PATCH] handle backslashes and isolated colons in depfile parser The logic was wrong if the input looked like foo : bar baz with a space before the colon. Test from Frances . --- configure.py | 2 +- src/depfile_parser.cc | 60 +++++++++++++++++--------------------- src/depfile_parser.in.cc | 15 +++++++--- src/depfile_parser_test.cc | 16 ++++++++++ 4 files changed, 55 insertions(+), 38 deletions(-) diff --git a/configure.py b/configure.py index 400cf42..c342677 100755 --- a/configure.py +++ b/configure.py @@ -143,7 +143,7 @@ if platform != 'mingw': n.comment('the depfile parser is generated using re2c.') n.rule('re2c', - command='re2c -b --no-generation-date -o $out $in', + command='re2c -b -i --no-generation-date -o $out $in', description='RE2C $out') # Generate the .cc file in the source directory so we can check it in. n.build(src('depfile_parser.cc'), 're2c', src('depfile_parser.in.cc')) diff --git a/src/depfile_parser.cc b/src/depfile_parser.cc index 10ab1d9..b6166e6 100644 --- a/src/depfile_parser.cc +++ b/src/depfile_parser.cc @@ -1,5 +1,4 @@ /* Generated by re2c 0.13.5 */ -#line 1 "src/depfile_parser.in.cc" // Copyright 2011 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,7 +34,6 @@ bool DepfileParser::Parse(const string& content, string* err) { const char* start = p; char yych; -#line 39 "src/depfile_parser.cc" { static const unsigned char yybm[] = { 0, 0, 0, 0, 0, 0, 0, 0, @@ -49,7 +47,7 @@ bool DepfileParser::Parse(const string& content, string* err) { 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, 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, @@ -77,60 +75,59 @@ bool DepfileParser::Parse(const string& content, string* err) { if (yych <= '@') { if (yych <= 0x1F) { if (yych == '\n') goto yy5; - goto yy8; + goto yy7; } else { if (yych <= ' ') goto yy5; - if (yych <= '*') goto yy8; + if (yych <= '*') goto yy7; if (yych <= ':') goto yy6; - goto yy8; + goto yy7; } } else { if (yych <= '^') { if (yych <= 'Z') goto yy6; if (yych == '\\') goto yy3; - goto yy8; + goto yy7; } else { - if (yych == '`') goto yy8; + if (yych == '`') goto yy7; if (yych <= 'z') goto yy6; - goto yy8; + goto yy7; } } yy2: -#line 50 "src/depfile_parser.in.cc" { continue; } -#line 102 "src/depfile_parser.cc" yy3: ++p; if ((yych = *p) == '\n') goto yy13; + goto yy10; yy4: -#line 60 "src/depfile_parser.in.cc" { - *err = "BUG: depfile lexer encountered unknown state"; - return false; + // 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)); + } + continue; } -#line 112 "src/depfile_parser.cc" yy5: yych = *++p; goto yy12; yy6: - ++p; - yych = *p; + yych = *++p; goto yy10; yy7: -#line 51 "src/depfile_parser.in.cc" + ++p; { - // Got a filename. - if (p[-1] == ':') { - out_ = StringPiece(start, p - start - 1); - } else { - ins_.push_back(StringPiece(start, p - start)); - } - continue; + *err = "BUG: depfile lexer encountered unknown state"; + return false; } -#line 131 "src/depfile_parser.cc" -yy8: - yych = *++p; - goto yy4; yy9: ++p; if (end <= p) break; @@ -139,7 +136,7 @@ yy10: if (yybm[0+yych] & 64) { goto yy9; } - goto yy7; + goto yy4; yy11: ++p; if (end <= p) break; @@ -151,11 +148,8 @@ yy12: goto yy2; yy13: ++p; -#line 49 "src/depfile_parser.in.cc" { continue; } -#line 157 "src/depfile_parser.cc" } -#line 64 "src/depfile_parser.in.cc" } return true; diff --git a/src/depfile_parser.in.cc b/src/depfile_parser.in.cc index 3d9a77e..8c04bdd 100644 --- a/src/depfile_parser.in.cc +++ b/src/depfile_parser.in.cc @@ -48,12 +48,19 @@ bool DepfileParser::Parse(const string& content, string* err) { '\\\n' { continue; } [ \n]* { continue; } - [a-zA-Z0-9+,/_:.-]+ { + [a-zA-Z0-9+,/\\_:.-]+ { // Got a filename. - if (p[-1] == ':') { - out_ = StringPiece(start, p - start - 1); + int len = p - start;; + if (start[len] == ':') + 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, p - start)); + ins_.push_back(StringPiece(start, len)); } continue; } diff --git a/src/depfile_parser_test.cc b/src/depfile_parser_test.cc index 3258529..52a1e5c 100644 --- a/src/depfile_parser_test.cc +++ b/src/depfile_parser_test.cc @@ -48,3 +48,19 @@ TEST(DepfileParser, Continuation) { EXPECT_EQ("foo.o", parser.out_.AsString()); EXPECT_EQ(2u, parser.ins_.size()); } + +TEST(DepfileParser, BackSlashes) { + DepfileParser parser; + string err; + EXPECT_TRUE(parser.Parse( +"Project\\Dir\\Build\\Release8\\Foo\\Foo.res : \\\n" +" Dir\\Library\\Foo.rc \\\n" +" Dir\\Library\\Version\\Bar.h \\\n" +" Dir\\Library\\Foo.ico \\\n" +" Project\\Thing\\Bar.tlb \\\n", + &err)); + ASSERT_EQ("", err); + EXPECT_EQ("Project\\Dir\\Build\\Release8\\Foo\\Foo.res", + parser.out_.AsString()); + EXPECT_EQ(4u, parser.ins_.size()); +}