aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShinichiro Hamaji <shinichiro.hamaji@gmail.com>2015-06-26 04:02:02 +0900
committerShinichiro Hamaji <shinichiro.hamaji@gmail.com>2015-06-26 16:42:23 +0900
commit420f7754d973242d4120ed67a942bfb386706494 (patch)
tree0a432b7e9a184ced56695ce4b95a267ebe298108
parente919d00f011abdded7b6e5a16888359c5d5996b1 (diff)
downloadandroid_build_kati-420f7754d973242d4120ed67a942bfb386706494.tar.gz
android_build_kati-420f7754d973242d4120ed67a942bfb386706494.tar.bz2
android_build_kati-420f7754d973242d4120ed67a942bfb386706494.zip
[C++] Parse override
-rw-r--r--ast.h8
-rw-r--r--eval.cc5
-rw-r--r--eval.h3
-rw-r--r--parser.cc48
-rw-r--r--testcase/override_export.mk16
-rw-r--r--testcase/override_override.mk15
-rw-r--r--testcase/override_rule.mk8
7 files changed, 94 insertions, 9 deletions
diff --git a/ast.h b/ast.h
index 28785c1..dbf13b3 100644
--- a/ast.h
+++ b/ast.h
@@ -33,10 +33,10 @@ enum struct AssignOp {
QUESTION_EQ,
};
-enum struct AssignDirective {
- NONE,
- OVERRIDE,
- EXPORT,
+enum struct AssignDirective : int {
+ NONE = 0,
+ OVERRIDE = 1,
+ EXPORT = 2,
};
enum struct CondOp {
diff --git a/eval.cc b/eval.cc
index a6c1e79..00d82c3 100644
--- a/eval.cc
+++ b/eval.cc
@@ -49,8 +49,9 @@ Evaluator::~Evaluator() {
}
Var* Evaluator::EvalRHS(StringPiece lhs, Value* rhs_v, StringPiece orig_rhs,
- AssignOp op) {
- const char* origin = is_bootstrap_ ? "default" : "file";
+ AssignOp op, bool is_override) {
+ const char* origin = (
+ is_bootstrap_ ? "default" : is_override ? "override" : "file");
Var* rhs = NULL;
bool needs_assign = true;
diff --git a/eval.h b/eval.h
index 70d5466..53b0825 100644
--- a/eval.h
+++ b/eval.h
@@ -70,7 +70,8 @@ class Evaluator {
void set_current_scope(Vars* v) { current_scope_ = v; }
private:
- Var* EvalRHS(StringPiece lhs, Value* rhs, StringPiece orig_rhs, AssignOp op);
+ Var* EvalRHS(StringPiece lhs, Value* rhs, StringPiece orig_rhs, AssignOp op,
+ bool is_override = false);
void DoInclude(const char* fname, bool should_exist);
const Vars* in_vars_;
diff --git a/parser.cc b/parser.cc
index adf59c1..d9611f9 100644
--- a/parser.cc
+++ b/parser.cc
@@ -77,6 +77,7 @@ class Parser {
if (!fixed_lineno_)
loc_.lineno++;
StringPiece line(buf_.data() + l_, e - l_);
+ orig_line_with_directives_ = line;
ParseLine(line);
if (!fixed_lineno_)
loc_.lineno += lf_cnt - 1;
@@ -99,11 +100,19 @@ class Parser {
(*make_directives_)["ifneq"] = &Parser::ParseIfeq;
(*make_directives_)["else"] = &Parser::ParseElse;
(*make_directives_)["endif"] = &Parser::ParseEndif;
+ (*make_directives_)["override"] = &Parser::ParseOverride;
+ (*make_directives_)["export"] = &Parser::ParseExport;
+ (*make_directives_)["unexport"] = &Parser::ParseUnexport;
else_if_directives_ = new DirectiveMap;
(*else_if_directives_)["ifdef"] = &Parser::ParseIfdef;
(*else_if_directives_)["ifndef"] = &Parser::ParseIfdef;
+ assign_directives_ = new DirectiveMap;
+ (*assign_directives_)["define"] = &Parser::ParseDefine;
+ (*assign_directives_)["export"] = &Parser::ParseExport;
+ (*assign_directives_)["override"] = &Parser::ParseOverride;
+
shortest_directive_len_ = 9999;
longest_directive_len_ = 0;
for (auto p : *make_directives_) {
@@ -135,6 +144,8 @@ class Parser {
return;
}
+ current_directive_ = AssignDirective::NONE;
+
if (line[0] == '\t' && state_ != ParserState::NOT_AFTER_RULE) {
CommandAST* ast = new CommandAST();
ast->set_loc(loc_);
@@ -152,6 +163,10 @@ class Parser {
return;
}
+ ParseRuleOrAssign(line);
+ }
+
+ void ParseRuleOrAssign(StringPiece line) {
size_t sep = FindTwoOutsideParen(line, ':', '=');
if (sep == string::npos) {
ParseRule(line, sep);
@@ -167,6 +182,13 @@ class Parser {
}
void ParseRule(StringPiece line, size_t sep) {
+ if (current_directive_ != AssignDirective::NONE) {
+ if (sep != string::npos) {
+ sep += orig_line_with_directives_.size() - line.size();
+ }
+ line = orig_line_with_directives_;
+ }
+
const bool is_rule = sep != string::npos && line[sep] == ':';
RuleAST* ast = new RuleAST();
ast->set_loc(loc_);
@@ -202,7 +224,7 @@ class Parser {
ast->rhs = ParseExpr(rhs);
ast->orig_rhs = rhs;
ast->op = op;
- ast->directive = AssignDirective::NONE;
+ ast->directive = current_directive_;
out_asts_->push_back(ast);
state_ = ParserState::NOT_AFTER_RULE;
}
@@ -249,7 +271,7 @@ class Parser {
ast->rhs = ParseExpr(rhs, ParseExprOpt::DEFINE);
ast->orig_rhs = rhs;
ast->op = AssignOp::EQ;
- ast->directive = AssignDirective::NONE;
+ ast->directive = current_directive_;
out_asts_->push_back(ast);
define_name_.clear();
}
@@ -364,6 +386,23 @@ class Parser {
}
}
+ void ParseOverride(StringPiece line, StringPiece directive) {
+ current_directive_ =
+ static_cast<AssignDirective>(
+ (static_cast<int>(current_directive_) |
+ static_cast<int>(AssignDirective::OVERRIDE)));
+ if (HandleDirective(line, assign_directives_))
+ return;
+
+ ParseRuleOrAssign(line);
+ }
+
+ void ParseExport(StringPiece line, StringPiece) {
+ }
+
+ void ParseUnexport(StringPiece line, StringPiece) {
+ }
+
void CheckIfStack(const char* keyword) {
if (if_stack_.empty()) {
Error(StringPrintf("*** extraneous `%s'.", keyword));
@@ -408,6 +447,9 @@ class Parser {
size_t define_start_;
int define_start_line_;
+ StringPiece orig_line_with_directives_;
+ AssignDirective current_directive_;
+
int num_if_nest_;
stack<IfState*> if_stack_;
@@ -416,6 +458,7 @@ class Parser {
static DirectiveMap* make_directives_;
static DirectiveMap* else_if_directives_;
+ static DirectiveMap* assign_directives_;
static size_t shortest_directive_len_;
static size_t longest_directive_len_;
};
@@ -442,6 +485,7 @@ void QuitParser() {
Parser::DirectiveMap* Parser::make_directives_;
Parser::DirectiveMap* Parser::else_if_directives_;
+Parser::DirectiveMap* Parser::assign_directives_;
size_t Parser::shortest_directive_len_;
size_t Parser::longest_directive_len_;
diff --git a/testcase/override_export.mk b/testcase/override_export.mk
new file mode 100644
index 0000000..99226d4
--- /dev/null
+++ b/testcase/override_export.mk
@@ -0,0 +1,16 @@
+# TODO: Fix
+
+override export A:=PASS_A
+export override B:=PASS_B
+export override define C
+PASS_C
+endef
+
+A:=FAIL_A
+B:=FAIL_B
+C:=FAIL_C
+
+test:
+ echo $$A
+ echo $$B
+ echo $$C
diff --git a/testcase/override_override.mk b/testcase/override_override.mk
new file mode 100644
index 0000000..3f66c12
--- /dev/null
+++ b/testcase/override_override.mk
@@ -0,0 +1,15 @@
+# TODO(go): Fix.
+
+override A:=PASS_A
+A:=FAIL_A
+
+override define B
+PASS_B
+endef
+B:=FAIL_B
+
+test:
+ echo $(A)
+ echo $(origin A)
+ echo $(B)
+ echo $(origin B)
diff --git a/testcase/override_rule.mk b/testcase/override_rule.mk
new file mode 100644
index 0000000..3811160
--- /dev/null
+++ b/testcase/override_rule.mk
@@ -0,0 +1,8 @@
+# TODO(go): Fix
+
+test: override
+
+A=OK
+override : A=PASS
+override :
+ echo $(A)