diff options
author | Fumitoshi Ukai <fumitoshi.ukai@gmail.com> | 2015-07-07 17:31:05 +0900 |
---|---|---|
committer | Fumitoshi Ukai <fumitoshi.ukai@gmail.com> | 2015-07-07 17:31:05 +0900 |
commit | 201df42f5df5f6a7f943dbb9f775ba857b261053 (patch) | |
tree | 7a4f9c7dc7cfcc385253bd85716d871e6952149d | |
parent | 9a17717fd5df84ece411c9284c944bb65f742668 (diff) | |
download | android_build_kati-201df42f5df5f6a7f943dbb9f775ba857b261053.tar.gz android_build_kati-201df42f5df5f6a7f943dbb9f775ba857b261053.tar.bz2 android_build_kati-201df42f5df5f6a7f943dbb9f775ba857b261053.zip |
fix equal_in_target.mk
-rw-r--r-- | ast.go | 6 | ||||
-rw-r--r-- | eval.go | 11 | ||||
-rw-r--r-- | evalcmd.go | 2 | ||||
-rw-r--r-- | expr.go | 3 | ||||
-rw-r--r-- | parser.go | 58 | ||||
-rw-r--r-- | rule_parser.go | 11 | ||||
-rw-r--r-- | rule_parser_test.go | 36 | ||||
-rw-r--r-- | testcase/equal_in_target.mk | 2 |
8 files changed, 115 insertions, 14 deletions
@@ -85,8 +85,10 @@ func (ast *assignAST) show() { // are expanded. type maybeRuleAST struct { srcpos - expr Value - semi []byte // after ';' if ';' exists + isRule bool // found literal ':' + expr Value + assign *assignAST // target specific var + semi []byte // after ';' if ';' exists } func (ast *maybeRuleAST) eval(ev *Evaluator) error { @@ -255,6 +255,8 @@ func (ev *Evaluator) evalMaybeRule(ast *maybeRuleAST) error { ev.lastRule = nil ev.srcpos = ast.srcpos + logf("maybe rule %s: %q assign:%v", ev.srcpos, ast.expr, ast.assign) + abuf := newBuf() aexpr := toExpr(ast.expr) var rhs expr @@ -267,10 +269,13 @@ func (ev *Evaluator) evalMaybeRule(ast *maybeRuleAST) error { return err } b := buf.Bytes() + if ast.isRule { + abuf.Write(b) + continue + } eq := findLiteralChar(b, []byte{'='}, true) if eq >= 0 { abuf.Write(b[:eq+1]) - rhs = expr{} if eq+1 < len(b) { rhs = append(rhs, tmpval(trimLeftSpaceBytes(b[eq+1:]))) } @@ -293,13 +298,13 @@ func (ev *Evaluator) evalMaybeRule(ast *maybeRuleAST) error { line := abuf.Bytes() r := &rule{srcpos: ast.srcpos} - assign, err := r.parse(line, rhs) + assign, err := r.parse(line, ast.assign, rhs) if err != nil { return ast.error(err) } freeBuf(abuf) if LogFlag { - logf("rule %q => outputs:%q, inputs:%q", ast.expr, r.outputs, r.inputs) + logf("rule %q assign:%v rhs:%v=> outputs:%q, inputs:%q", ast.expr, ast.assign, rhs, r.outputs, r.inputs) } // TODO: Pretty print. @@ -296,7 +296,7 @@ func createRunners(ctx *execContext, n *DepNode) ([]runner, bool, error) { restore := ctx.ev.vars.save(k) defer restore() ctx.ev.vars[k] = v - logf("tsv: %s=%s", k, v) + logf("set tsv: %s=%s", k, v) } ctx.ev.filename = n.Filename @@ -124,6 +124,9 @@ func compactExpr(e expr) Value { return e } func toExpr(v Value) expr { + if v == nil { + return nil + } if e, ok := v.(expr); ok { return e } @@ -162,7 +162,8 @@ func (p *parser) handleRuleOrAssign(line []byte) { if p.handleAssign(line) { return } - // not assignment + // not assignment. + // ie. no '=' found or ':' found before '=' (except ':=') p.parseMaybeRule(rline, semi) return } @@ -213,6 +214,54 @@ func (p *parser) parseMaybeRule(line, semi []byte) { p.err = p.srcpos().errorf("*** commands commence before first target.") return } + var assign *assignAST + ci := findLiteralChar(line, []byte{':'}, true) + if ci >= 0 { + eqi := findLiteralChar(line[ci+1:], []byte{'='}, true) + if eqi == 0 { + panic(fmt.Sprintf("unexpected eq after colon: %q", line)) + } + if eqi > 0 { + var lhsbytes []byte + op := "=" + switch line[ci+1+eqi-1] { + case ':', '+', '?': + lhsbytes = append(lhsbytes, line[ci+1:ci+1+eqi-1]...) + op = string(line[ci+1+eqi-1 : ci+1+eqi+1]) + default: + lhsbytes = append(lhsbytes, line[ci+1:ci+1+eqi]...) + } + + lhsbytes = trimSpaceBytes(lhsbytes) + lhs, _, err := parseExpr(lhsbytes, nil, parseOp{}) + if err != nil { + p.err = p.srcpos().error(err) + return + } + var rhsbytes []byte + rhsbytes = append(rhsbytes, line[ci+1+eqi+1:]...) + if semi != nil { + rhsbytes = append(rhsbytes, ';') + rhsbytes = append(rhsbytes, concatline(semi)...) + } + rhsbytes = trimLeftSpaceBytes(rhsbytes) + semi = nil + rhs, _, err := parseExpr(rhsbytes, nil, parseOp{}) + if err != nil { + p.err = p.srcpos().error(err) + return + } + + // TODO(ukai): support override, export in target specific var. + assign = &assignAST{ + lhs: lhs, + rhs: rhs, + op: op, + } + assign.srcpos = p.srcpos() + line = line[:ci+1] + } + } expr, _, err := parseExpr(line, nil, parseOp{}) if err != nil { p.err = p.srcpos().error(err) @@ -220,10 +269,13 @@ func (p *parser) parseMaybeRule(line, semi []byte) { } // TODO(ukai): remove ast, and eval here. rast := &maybeRuleAST{ - expr: expr, - semi: semi, + isRule: ci >= 0, + expr: expr, + assign: assign, + semi: semi, } rast.srcpos = p.srcpos() + logf("stmt: %#v", rast) p.addStatement(rast) } diff --git a/rule_parser.go b/rule_parser.go index 983358a..3b03bab 100644 --- a/rule_parser.go +++ b/rule_parser.go @@ -133,8 +133,9 @@ func (r *rule) parseVar(s []byte, rhs expr) (*assignAST, error) { // parse parses rule line. // line is rule line until '=', or before ';' -// rhs is not nil, if line ended with '=' (target specific var) -func (r *rule) parse(line []byte, rhs expr) (*assignAST, error) { +// assign is not nil, if line was known as target specific var '<xxx>: <v>=<val>' +// rhs is not nil, if line ended with '=' (target specific var after evaluated) +func (r *rule) parse(line []byte, assign *assignAST, rhs expr) (*assignAST, error) { var removed bool line, removed = removeComment(line) if removed { @@ -178,6 +179,12 @@ func (r *rule) parse(line []byte, rhs expr) (*assignAST, error) { } rest := line[index:] + if assign != nil { + if len(rest) > 0 { + panic(fmt.Sprintf("pattern specific var? line:%q", line)) + } + return assign, nil + } if rhs != nil { assign, err := r.parseVar(rest, rhs) if err != nil { diff --git a/rule_parser_test.go b/rule_parser_test.go index 93065a3..be12041 100644 --- a/rule_parser_test.go +++ b/rule_parser_test.go @@ -22,6 +22,7 @@ import ( func TestRuleParser(t *testing.T) { for _, tc := range []struct { in string + tsv *assignAST rhs expr want rule assign *assignAST @@ -110,6 +111,22 @@ func TestRuleParser(t *testing.T) { }, }, { + in: "foo:", + tsv: &assignAST{ + lhs: literal("CFLAGS"), + rhs: literal("-g"), + op: "=", + }, + want: rule{ + outputs: []string{"foo"}, + }, + assign: &assignAST{ + lhs: literal("CFLAGS"), + rhs: literal("-g"), + op: "=", + }, + }, + { in: "foo: CFLAGS=", rhs: expr{literal("-g")}, want: rule{ @@ -146,6 +163,23 @@ func TestRuleParser(t *testing.T) { op: ":=", }, }, + { + in: "%.o:", + tsv: &assignAST{ + lhs: literal("CFLAGS"), + rhs: literal("-g"), + op: ":=", + }, + want: rule{ + outputs: []string{}, + outputPatterns: []pattern{pattern{suffix: ".o"}}, + }, + assign: &assignAST{ + lhs: literal("CFLAGS"), + rhs: literal("-g"), + op: ":=", + }, + }, /* TODO { in: "foo.o: %.c: %.c", @@ -154,7 +188,7 @@ func TestRuleParser(t *testing.T) { */ } { got := &rule{} - assign, err := got.parse([]byte(tc.in), tc.rhs) + assign, err := got.parse([]byte(tc.in), tc.tsv, tc.rhs) if tc.err != "" { if err == nil { t.Errorf(`r.parse(%q, %v)=_, <nil>, want _, %q`, tc.in, tc.rhs, tc.err) diff --git a/testcase/equal_in_target.mk b/testcase/equal_in_target.mk index 8aceb50..faf532c 100644 --- a/testcase/equal_in_target.mk +++ b/testcase/equal_in_target.mk @@ -1,5 +1,3 @@ -# TODO: Fix - TSV:=test: A=PASS A_EQ_B:=A=B EQ== |