('a' <= c && c <= 'z') ||
('+' <= c && c <= '9') || // +,-./ and numbers
('A' <= c && c <= 'Z') ||
- (c == '_');
+ (c == '_') || (c == '@');
}
bool Parser::Token(const string& expected, string* err) {
bool ParseLet(string* err);
bool ParseEdge(string* err);
+ string ExpandFile(const string& file);
+
State* state_;
Parser parser_;
+ string builddir_;
};
bool ManifestParser::Load(const string& filename, string* err) {
return false;
state_->AddBinding(name, value);
+ if (name == "builddir") {
+ builddir_ = value;
+ if (!builddir_.empty() && builddir_[builddir_.size() - 1] != '/')
+ builddir_.push_back('/');
+ }
return true;
}
return parser_.Error("expected output file list", err);
if (out == ":")
break;
- outs.push_back(out);
+ outs.push_back(ExpandFile(out));
}
string rule_name;
string in;
if (!parser_.ReadToken(&in))
break;
- ins.push_back(in);
+ ins.push_back(ExpandFile(in));
}
if (!parser_.Newline(err))
return true;
}
+string ManifestParser::ExpandFile(const string& file) {
+ if (!file.empty() && file[0] == '@')
+ return builddir_ + file.substr(1);
+ return file;
+}
+
}
}
+TEST(Parser, BuildDir) {
+ State state;
+ ASSERT_NO_FATAL_FAILURE(AssertParse(&state,
+"builddir = out\n"
+"rule cat\n"
+"command cat @in > $out\n"
+"build @bin: cat @a.o\n"
+"build @a.o: cat a.cc\n"));
+ state.stat_cache()->Dump();
+ ASSERT_TRUE(state.LookupNode("out/a.o"));
+}
+
+
TEST(State, Basic) {
State state;
Rule* rule = state.AddRule("cat", "cat @in > $out");