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) {
#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();
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,
}
}
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;
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] == ':') {
}
continue;
}
-#line 119 "src/depfile_parser.cc"
+#line 131 "src/depfile_parser.cc"
yy8:
yych = *++p;
goto yy4;
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;
#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();
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')
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);
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_) {
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_;
/// 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);
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.
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<StringPiece> ins_;
-};
-
struct EvalString;
struct State;
#include <gtest/gtest.h>
+#include "depfile_parser.h"
#include "graph.h"
#include "state.h"
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",
EXPECT_EQ(4u, parser.ins_.size());
}
-TEST(MakefileParser, EarlyNewlineAndWhitespace) {
- MakefileParser parser;
+TEST(DepfileParser, EarlyNewlineAndWhitespace) {
+ DepfileParser parser;
string err;
EXPECT_TRUE(parser.Parse(
" \\\n"
ASSERT_EQ("", err);
}
-TEST(MakefileParser, Continuation) {
- MakefileParser parser;
+TEST(DepfileParser, Continuation) {
+ DepfileParser parser;
string err;
EXPECT_TRUE(parser.Parse(
"foo.o: \\\n"