From 8aae49d6f74fa5124f080de814c7ff37144b6373 Mon Sep 17 00:00:00 2001 From: Evan Martin Date: Wed, 7 Dec 2011 12:14:30 -0800 Subject: remove makefile parsing code, use depfile code instead --- src/build_test.cc | 2 +- src/depfile_parser.cc | 32 ++++++++++++++++++++++---------- src/depfile_parser.in.cc | 12 ++++++++++++ src/parsers.cc | 47 +++-------------------------------------------- src/parsers.h | 22 +--------------------- src/parsers_test.cc | 13 +++++++------ 6 files changed, 46 insertions(+), 82 deletions(-) diff --git a/src/build_test.cc b/src/build_test.cc index cf75e04..f7e4a5c 100644 --- a/src/build_test.cc +++ b/src/build_test.cc @@ -486,7 +486,7 @@ TEST_F(BuildTest, DepFileParseError) { fs_.Create("foo.c", now_, ""); fs_.Create("foo.o.d", now_, "foo.o blah.h bar.h\n"); EXPECT_FALSE(builder_.AddTarget("foo.o", &err)); - EXPECT_EQ("foo.o.d: line 1, col 7: expected ':', got 'blah.h'", err); + EXPECT_EQ("expected depfile 'foo.o.d' to mention 'foo.o', got ''", err); } TEST_F(BuildTest, OrderOnlyDeps) { diff --git a/src/depfile_parser.cc b/src/depfile_parser.cc index 7be4a60..10ab1d9 100644 --- a/src/depfile_parser.cc +++ b/src/depfile_parser.cc @@ -16,6 +16,18 @@ #include "depfile_parser.h" +// A note on backslashes in Makefiles, from reading the docs: +// Backslash-newline is the line continuation character. +// Backslash-# escapes a # (otherwise meaningful as a comment start). +// Backslash-% escapes a % (otherwise meaningful as a special). +// Finally, quoting the GNU manual, "Backslashes that are not in danger +// of quoting ‘%’ characters go unmolested." +// 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. +// If anyone actually has depfiles that rely on the more complicated +// behavior we can adjust this. bool DepfileParser::Parse(const string& content, string* err) { const char* p = content.data(); const char* end = content.data() + content.size(); @@ -23,7 +35,7 @@ bool DepfileParser::Parse(const string& content, string* err) { const char* start = p; char yych; -#line 27 "src/depfile_parser.cc" +#line 39 "src/depfile_parser.cc" { static const unsigned char yybm[] = { 0, 0, 0, 0, 0, 0, 0, 0, @@ -84,19 +96,19 @@ bool DepfileParser::Parse(const string& content, string* err) { } } yy2: -#line 38 "src/depfile_parser.in.cc" +#line 50 "src/depfile_parser.in.cc" { continue; } -#line 90 "src/depfile_parser.cc" +#line 102 "src/depfile_parser.cc" yy3: ++p; if ((yych = *p) == '\n') goto yy13; yy4: -#line 48 "src/depfile_parser.in.cc" +#line 60 "src/depfile_parser.in.cc" { *err = "BUG: depfile lexer encountered unknown state"; return false; } -#line 100 "src/depfile_parser.cc" +#line 112 "src/depfile_parser.cc" yy5: yych = *++p; goto yy12; @@ -105,7 +117,7 @@ yy6: yych = *p; goto yy10; yy7: -#line 39 "src/depfile_parser.in.cc" +#line 51 "src/depfile_parser.in.cc" { // Got a filename. if (p[-1] == ':') { @@ -115,7 +127,7 @@ yy7: } continue; } -#line 119 "src/depfile_parser.cc" +#line 131 "src/depfile_parser.cc" yy8: yych = *++p; goto yy4; @@ -139,11 +151,11 @@ yy12: goto yy2; yy13: ++p; -#line 37 "src/depfile_parser.in.cc" +#line 49 "src/depfile_parser.in.cc" { continue; } -#line 145 "src/depfile_parser.cc" +#line 157 "src/depfile_parser.cc" } -#line 52 "src/depfile_parser.in.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 1e22ca9..3d9a77e 100644 --- a/src/depfile_parser.in.cc +++ b/src/depfile_parser.in.cc @@ -14,6 +14,18 @@ #include "depfile_parser.h" +// A note on backslashes in Makefiles, from reading the docs: +// Backslash-newline is the line continuation character. +// Backslash-# escapes a # (otherwise meaningful as a comment start). +// Backslash-% escapes a % (otherwise meaningful as a special). +// Finally, quoting the GNU manual, "Backslashes that are not in danger +// of quoting ‘%’ characters go unmolested." +// 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. +// If anyone actually has depfiles that rely on the more complicated +// behavior we can adjust this. bool DepfileParser::Parse(const string& content, string* err) { const char* p = content.data(); const char* end = content.data() + content.size(); diff --git a/src/parsers.cc b/src/parsers.cc index 4920496..ea73287 100644 --- a/src/parsers.cc +++ b/src/parsers.cc @@ -74,14 +74,12 @@ void Tokenizer::SkipWhitespace(bool newline) { if (token_.type_ == Token::NEWLINE && newline) Newline(NULL); - const char kContinuation = makefile_flavor_ ? '\\' : '$'; - while (cur_ < end_) { if (*cur_ == ' ') { ++cur_; } else if (newline && *cur_ == '\n') { Newline(NULL); - } else if (*cur_ == kContinuation && cur_ + 1 < end_ && cur_[1] == '\n') { + } else if (*cur_ == '$' && cur_ + 1 < end_ && cur_[1] == '\n') { ++cur_; ++cur_; } else if (*cur_ == '#' && cur_ == cur_line_) { while (cur_ < end_ && *cur_ != '\n') @@ -166,23 +164,10 @@ bool Tokenizer::ReadIdent(string* out) { return true; } -// A note on backslashes in Makefiles, from reading the docs: -// Backslash-newline is the line continuation character. -// Backslash-# escapes a # (otherwise meaningful as a comment start). -// Backslash-% escapes a % (otherwise meaningful as a special). -// Finally, quoting the GNU manual, "Backslashes that are not in danger -// of quoting ‘%’ characters go unmolested." -// 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. -// If anyone actually has depfiles that rely on the more complicated -// behavior we can adjust this. bool Tokenizer::ReadToNewline(string *text, string* err, size_t max_length) { // XXX token_.clear(); - const char kContinuation = makefile_flavor_ ? '\\' : '$'; while (cur_ < end_ && *cur_ != '\n') { - if (*cur_ == kContinuation) { + if (*cur_ == '$') { // Might be a line continuation; peek ahead to check. if (cur_ + 1 >= end_) return Error("unexpected eof", err); @@ -212,7 +197,7 @@ Token::Type Tokenizer::PeekToken() { return token_.type_; token_.pos_ = cur_; - if (!makefile_flavor_ && cur_indent_ == -1) { + if (cur_indent_ == -1) { cur_indent_ = cur_ - cur_line_; if (cur_indent_ != last_indent_) { if (cur_indent_ > last_indent_) { @@ -271,32 +256,6 @@ void Tokenizer::ConsumeToken() { token_.Clear(); } -MakefileParser::MakefileParser() { - tokenizer_.SetMakefileFlavor(); -} - -bool MakefileParser::Parse(const string& input, string* err) { - tokenizer_.Start(input.data(), input.data() + input.size()); - - tokenizer_.SkipWhitespace(true); - - if (!tokenizer_.ReadIdent(&out_)) - return tokenizer_.ErrorExpected("output filename", err); - if (!tokenizer_.ExpectToken(Token::COLON, err)) - return false; - while (tokenizer_.PeekToken() == Token::IDENT) { - StringPiece in; - tokenizer_.ReadIdent(&in); - ins_.push_back(in); - } - if (!tokenizer_.ExpectToken(Token::NEWLINE, err)) - return false; - if (!tokenizer_.ExpectToken(Token::TEOF, err)) - return false; - - return true; -} - ManifestParser::ManifestParser(State* state, FileReader* file_reader) : state_(state), file_reader_(file_reader) { env_ = &state->bindings_; diff --git a/src/parsers.h b/src/parsers.h index 6bdca77..101b278 100644 --- a/src/parsers.h +++ b/src/parsers.h @@ -52,18 +52,10 @@ struct Token { /// Processes an input stream into Tokens. struct Tokenizer { - Tokenizer() - : makefile_flavor_(false), + Tokenizer() : token_(Token::NONE), last_indent_(0), cur_indent_(-1) {} - /// Tokenization differs slightly between ninja files and Makefiles. - /// By default we tokenize as ninja files; calling this changes to - /// Makefile-style tokenization. - void SetMakefileFlavor() { - makefile_flavor_ = true; - } - void Start(const char* start, const char* end); /// Report an error at a particular location. bool ErrorAt(const char* pos, const string& message, string* err); @@ -88,8 +80,6 @@ struct Tokenizer { Token::Type PeekToken(); void ConsumeToken(); - bool makefile_flavor_; - const char* start_; /// Start of the input. const char* cur_; /// Current position within the input. const char* end_; /// End of the input. @@ -99,16 +89,6 @@ struct Tokenizer { int last_indent_, cur_indent_; }; -/// Parses simple Makefiles as generated by gcc. -struct MakefileParser { - MakefileParser(); - bool Parse(const string& input, string* err); - - Tokenizer tokenizer_; - StringPiece out_; - vector ins_; -}; - struct EvalString; struct State; diff --git a/src/parsers_test.cc b/src/parsers_test.cc index f23a178..0e6d532 100644 --- a/src/parsers_test.cc +++ b/src/parsers_test.cc @@ -16,6 +16,7 @@ #include +#include "depfile_parser.h" #include "graph.h" #include "state.h" @@ -487,8 +488,8 @@ TEST_F(ParserTest, DefaultStatements) { EXPECT_EQ("c", nodes[2]->path()); } -TEST(MakefileParser, Basic) { - MakefileParser parser; +TEST(DepfileParser, Basic) { + DepfileParser parser; string err; EXPECT_TRUE(parser.Parse( "build/ninja.o: ninja.cc ninja.h eval_env.h manifest_parser.h\n", @@ -498,8 +499,8 @@ TEST(MakefileParser, Basic) { EXPECT_EQ(4u, parser.ins_.size()); } -TEST(MakefileParser, EarlyNewlineAndWhitespace) { - MakefileParser parser; +TEST(DepfileParser, EarlyNewlineAndWhitespace) { + DepfileParser parser; string err; EXPECT_TRUE(parser.Parse( " \\\n" @@ -508,8 +509,8 @@ TEST(MakefileParser, EarlyNewlineAndWhitespace) { ASSERT_EQ("", err); } -TEST(MakefileParser, Continuation) { - MakefileParser parser; +TEST(DepfileParser, Continuation) { + DepfileParser parser; string err; EXPECT_TRUE(parser.Parse( "foo.o: \\\n" -- cgit v0.12