diff options
Diffstat (limited to 'src/manifest_parser.cc')
-rw-r--r-- | src/manifest_parser.cc | 33 |
1 files changed, 18 insertions, 15 deletions
diff --git a/src/manifest_parser.cc b/src/manifest_parser.cc index 3593567..20be7f3 100644 --- a/src/manifest_parser.cc +++ b/src/manifest_parser.cc @@ -15,6 +15,7 @@ #include "manifest_parser.h" #include <stdio.h> +#include <stdlib.h> #include <vector> #include "graph.h" @@ -27,20 +28,30 @@ ManifestParser::ManifestParser(State* state, FileReader* file_reader) : state_(state), file_reader_(file_reader) { env_ = &state->bindings_; } -bool ManifestParser::Load(const string& filename, string* err) { + +bool ManifestParser::Load(const string& filename, string* err, Lexer* parent) { + METRIC_RECORD(".ninja parse"); string contents; string read_err; if (!file_reader_->ReadFile(filename, &contents, &read_err)) { *err = "loading '" + filename + "': " + read_err; + if (parent) + parent->Error(string(*err), err); return false; } - contents.resize(contents.size() + 10); + + // The lexer needs a nul byte at the end of its input, to know when it's done. + // It takes a StringPiece, and StringPiece's string constructor uses + // string::data(). data()'s return value isn't guaranteed to be + // null-terminated (although in practice - libc++, libstdc++, msvc's stl -- + // it is, and C++11 demands that too), so add an explicit nul byte. + contents.resize(contents.size() + 1); + return Parse(filename, contents, err); } bool ManifestParser::Parse(const string& filename, const string& input, string* err) { - METRIC_RECORD(".ninja parse"); lexer_.Start(filename, input); for (;;) { @@ -145,10 +156,8 @@ bool ManifestParser::ParseRule(string* err) { if (!ExpectToken(Lexer::NEWLINE, err)) return false; - if (state_->LookupRule(name) != NULL) { - *err = "duplicate rule '" + name + "'"; - return false; - } + if (state_->LookupRule(name) != NULL) + return lexer_.Error("duplicate rule '" + name + "'", err); Rule* rule = new Rule(name); // XXX scoped_ptr @@ -306,7 +315,7 @@ bool ManifestParser::ParseEdge(string* err) { if (!pool_name.empty()) { Pool* pool = state_->LookupPool(pool_name); if (pool == NULL) - return lexer_.Error("unknown pool name", err); + return lexer_.Error("unknown pool name '" + pool_name + "'", err); edge->pool_ = pool; } @@ -339,17 +348,11 @@ bool ManifestParser::ParseEdge(string* err) { } bool ManifestParser::ParseFileInclude(bool new_scope, string* err) { - // XXX this should use ReadPath! EvalString eval; if (!lexer_.ReadPath(&eval, err)) return false; string path = eval.Evaluate(env_); - string contents; - string read_err; - if (!file_reader_->ReadFile(path, &contents, &read_err)) - return lexer_.Error("loading '" + path + "': " + read_err, err); - ManifestParser subparser(state_, file_reader_); if (new_scope) { subparser.env_ = new BindingEnv(env_); @@ -357,7 +360,7 @@ bool ManifestParser::ParseFileInclude(bool new_scope, string* err) { subparser.env_ = env_; } - if (!subparser.Parse(path, contents, err)) + if (!subparser.Load(path, err, &lexer_)) return false; if (!ExpectToken(Lexer::NEWLINE, err)) |