blob: 30308c3b33738c9a2150df3d66d769e7ac6aa2de [file] [log] [blame]
Shinichiro Hamajib69bf8a2015-06-10 14:52:06 +09001// Copyright 2015 Google Inc. All rights reserved
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +090015package kati
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090016
17import (
18 "bytes"
Shinichiro Hamaji4220be32015-05-26 13:30:18 +090019 "crypto/sha1"
Fumitoshi Ukaif8efa0a2015-03-30 18:10:11 +090020 "fmt"
Fumitoshi Ukai9042b992015-06-23 16:10:27 +090021 "os"
Shinichiro Hamaji2450bfa2015-05-29 16:43:28 +090022 "path/filepath"
Fumitoshi Ukai612e0862015-08-10 16:09:09 +090023 "strconv"
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090024 "strings"
Fumitoshi Ukai0af44522015-06-25 15:26:08 +090025 "sync"
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +090026
27 "github.com/golang/glog"
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090028)
29
Fumitoshi Ukai0af44522015-06-25 15:26:08 +090030type fileState int
Fumitoshi Ukai936de102015-06-08 11:21:16 +090031
Shinichiro Hamaji45cde1d2015-05-25 18:21:23 +090032const (
Fumitoshi Ukai0af44522015-06-25 15:26:08 +090033 fileExists fileState = iota
34 fileNotExists
35 fileInconsistent // Modified during kati is running.
Shinichiro Hamaji45cde1d2015-05-25 18:21:23 +090036)
37
Fumitoshi Ukai0af44522015-06-25 15:26:08 +090038type accessedMakefile struct {
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +090039 Filename string
Shinichiro Hamaji4220be32015-05-26 13:30:18 +090040 Hash [sha1.Size]byte
Fumitoshi Ukai0af44522015-06-25 15:26:08 +090041 State fileState
42}
43
44type accessCache struct {
45 mu sync.Mutex
46 m map[string]*accessedMakefile
47}
48
49func newAccessCache() *accessCache {
50 return &accessCache{
51 m: make(map[string]*accessedMakefile),
52 }
53}
54
55func (ac *accessCache) update(fn string, hash [sha1.Size]byte, st fileState) string {
56 if ac == nil {
57 return ""
58 }
59 ac.mu.Lock()
60 defer ac.mu.Unlock()
61 rm, present := ac.m[fn]
62 if present {
63 switch rm.State {
64 case fileExists:
65 if st != fileExists {
66 return fmt.Sprintf("%s was removed after the previous read", fn)
67 } else if !bytes.Equal(hash[:], rm.Hash[:]) {
68 ac.m[fn].State = fileInconsistent
69 return fmt.Sprintf("%s was modified after the previous read", fn)
70 }
71 return ""
72 case fileNotExists:
73 if st != fileNotExists {
74 ac.m[fn].State = fileInconsistent
75 return fmt.Sprintf("%s was created after the previous read", fn)
76 }
77 case fileInconsistent:
78 return ""
79 }
80 return ""
81 }
82 ac.m[fn] = &accessedMakefile{
83 Filename: fn,
84 Hash: hash,
85 State: st,
86 }
87 return ""
88}
89
90func (ac *accessCache) Slice() []*accessedMakefile {
91 if ac == nil {
92 return nil
93 }
94 ac.mu.Lock()
95 defer ac.mu.Unlock()
96 r := []*accessedMakefile{}
97 for _, v := range ac.m {
98 r = append(r, v)
99 }
100 return r
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +0900101}
102
Fumitoshi Ukai08eda652015-06-25 16:27:10 +0900103type evalResult struct {
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900104 vars Vars
Fumitoshi Ukaiadc14442015-06-25 16:10:30 +0900105 rules []*rule
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900106 ruleVars map[string]Vars
107 accessedMks []*accessedMakefile
108 exports map[string]bool
Fumitoshi Ukai09fcd522015-07-15 14:31:50 +0900109 vpaths searchPaths
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900110}
111
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900112type srcpos struct {
113 filename string
114 lineno int
115}
116
117func (p srcpos) String() string {
118 return fmt.Sprintf("%s:%d", p.filename, p.lineno)
119}
120
121// EvalError is an error in kati evaluation.
122type EvalError struct {
123 Filename string
124 Lineno int
125 Err error
126}
127
128func (e EvalError) Error() string {
129 return fmt.Sprintf("%s:%d: %v", e.Filename, e.Lineno, e.Err)
130}
131
132func (p srcpos) errorf(f string, args ...interface{}) error {
133 return EvalError{
134 Filename: p.filename,
135 Lineno: p.lineno,
136 Err: fmt.Errorf(f, args...),
137 }
138}
139
140func (p srcpos) error(err error) error {
141 if _, ok := err.(EvalError); ok {
142 return err
143 }
144 return EvalError{
145 Filename: p.filename,
146 Lineno: p.lineno,
147 Err: err,
148 }
149}
150
151// Evaluator manages makefile evaluation.
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900152type Evaluator struct {
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900153 paramVars []tmpval // $1 => paramVars[1]
Shinichiro Hamajia485d2f2015-04-16 14:03:24 +0900154 outVars Vars
Fumitoshi Ukaiadc14442015-06-25 16:10:30 +0900155 outRules []*rule
Shinichiro Hamajia485d2f2015-04-16 14:03:24 +0900156 outRuleVars map[string]Vars
157 vars Vars
Fumitoshi Ukaiadc14442015-06-25 16:10:30 +0900158 lastRule *rule
Shinichiro Hamajia485d2f2015-04-16 14:03:24 +0900159 currentScope Vars
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900160 cache *accessCache
Shinichiro Hamaji7e521422015-05-29 14:23:30 +0900161 exports map[string]bool
Fumitoshi Ukai09fcd522015-07-15 14:31:50 +0900162 vpaths []vpath
Shinichiro Hamaji51d53d92015-03-30 18:32:16 +0900163
Fumitoshi Ukaie5bf7582015-07-28 16:07:51 +0900164 avoidIO bool
165 hasIO bool
166 // delayedOutputs are commands which should run at ninja-time
167 // (i.e., info, warning, and error).
168 delayedOutputs []string
169
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900170 srcpos
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900171}
172
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900173// NewEvaluator creates new Evaluator.
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900174func NewEvaluator(vars map[string]Var) *Evaluator {
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900175 return &Evaluator{
Shinichiro Hamajia485d2f2015-04-16 14:03:24 +0900176 outVars: make(Vars),
177 vars: vars,
178 outRuleVars: make(map[string]Vars),
Shinichiro Hamaji7e521422015-05-29 14:23:30 +0900179 exports: make(map[string]bool),
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900180 }
181}
182
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900183func (ev *Evaluator) args(buf *evalBuffer, args ...Value) ([][]byte, error) {
Fumitoshi Ukai77411fb2015-06-19 15:46:21 +0900184 pos := make([]int, 0, len(args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900185 for _, arg := range args {
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900186 buf.resetSep()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900187 err := arg.Eval(buf, ev)
188 if err != nil {
189 return nil, err
190 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900191 pos = append(pos, buf.Len())
Fumitoshi Ukai6ac7f692015-04-15 17:13:51 +0900192 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900193 v := buf.Bytes()
Fumitoshi Ukaid0bf88c2015-05-08 10:54:32 +0900194 buf.args = buf.args[:0]
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900195 s := 0
196 for _, p := range pos {
Fumitoshi Ukaid0bf88c2015-05-08 10:54:32 +0900197 buf.args = append(buf.args, v[s:p])
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900198 s = p
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900199 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900200 return buf.args, nil
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900201}
202
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900203func (ev *Evaluator) evalAssign(ast *assignAST) error {
Shinichiro Hamaji0b93c862015-04-07 06:15:15 +0900204 ev.lastRule = nil
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900205 lhs, rhs, err := ev.evalAssignAST(ast)
206 if err != nil {
207 return err
208 }
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900209 if glog.V(1) {
210 glog.Infof("ASSIGN: %s=%q (flavor:%q)", lhs, rhs, rhs.Flavor())
Fumitoshi Ukai5c04ad82015-06-18 16:14:04 +0900211 }
Fumitoshi Ukaie16c2b72015-06-19 00:15:59 +0900212 if lhs == "" {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900213 return ast.errorf("*** empty variable name.")
Shinichiro Hamaji46ee5cf2015-04-06 18:07:10 +0900214 }
Fumitoshi Ukai953ce6f2015-04-04 00:38:53 +0900215 ev.outVars.Assign(lhs, rhs)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900216 return nil
Fumitoshi Ukai953ce6f2015-04-04 00:38:53 +0900217}
218
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900219func (ev *Evaluator) evalAssignAST(ast *assignAST) (string, Var, error) {
220 ev.srcpos = ast.srcpos
Shinichiro Hamaji51d53d92015-03-30 18:32:16 +0900221
Fumitoshi Ukai00178d12015-04-18 00:11:05 +0900222 var lhs string
Shinichiro Hamaji7825b652015-06-04 13:47:14 +0900223 switch v := ast.lhs.(type) {
Fumitoshi Ukai00178d12015-04-18 00:11:05 +0900224 case literal:
225 lhs = string(v)
226 case tmpval:
227 lhs = string(v)
228 default:
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900229 buf := newEbuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900230 err := v.Eval(buf, ev)
231 if err != nil {
232 return "", nil, err
233 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900234 lhs = string(trimSpaceBytes(buf.Bytes()))
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900235 buf.release()
Fumitoshi Ukai00178d12015-04-18 00:11:05 +0900236 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900237 rhs, err := ast.evalRHS(ev, lhs)
238 if err != nil {
239 return "", nil, err
240 }
241 return lhs, rhs, nil
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900242}
243
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900244func (ev *Evaluator) setTargetSpecificVar(assign *assignAST, output string) error {
Shinichiro Hamajia485d2f2015-04-16 14:03:24 +0900245 vars, present := ev.outRuleVars[output]
246 if !present {
247 vars = make(Vars)
248 ev.outRuleVars[output] = vars
249 }
250 ev.currentScope = vars
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900251 lhs, rhs, err := ev.evalAssignAST(assign)
252 if err != nil {
253 return err
254 }
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900255 if glog.V(1) {
256 glog.Infof("rule outputs:%q assign:%q%s%q (flavor:%q)", output, lhs, assign.op, rhs, rhs.Flavor())
Fumitoshi Ukai5c04ad82015-06-18 16:14:04 +0900257 }
Fumitoshi Ukai7bf992d2015-06-25 12:42:19 +0900258 vars.Assign(lhs, &targetSpecificVar{v: rhs, op: assign.op})
Shinichiro Hamajia485d2f2015-04-16 14:03:24 +0900259 ev.currentScope = nil
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900260 return nil
Shinichiro Hamajia485d2f2015-04-16 14:03:24 +0900261}
262
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900263func (ev *Evaluator) evalMaybeRule(ast *maybeRuleAST) error {
Shinichiro Hamaji0b93c862015-04-07 06:15:15 +0900264 ev.lastRule = nil
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900265 ev.srcpos = ast.srcpos
Shinichiro Hamaji51d53d92015-03-30 18:32:16 +0900266
Fumitoshi Ukai6addc2f2015-07-22 11:33:35 +0900267 if glog.V(1) {
268 glog.Infof("maybe rule %s: %q assign:%v", ev.srcpos, ast.expr, ast.assign)
269 }
Fumitoshi Ukai201df422015-07-07 17:31:05 +0900270
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900271 abuf := newEbuf()
Fumitoshi Ukaib97be672015-07-02 15:12:48 +0900272 aexpr := toExpr(ast.expr)
273 var rhs expr
274 semi := ast.semi
275 for i, v := range aexpr {
Fumitoshi Ukai66c4ee12015-07-28 16:31:58 +0900276 var hashFound bool
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900277 var buf evalBuffer
278 buf.resetSep()
Fumitoshi Ukai66c4ee12015-07-28 16:31:58 +0900279 switch v.(type) {
280 case literal, tmpval:
281 s := v.String()
282 i := strings.Index(s, "#")
283 if i >= 0 {
284 hashFound = true
285 v = tmpval(trimRightSpaceBytes([]byte(s[:i])))
286 }
287 }
Fumitoshi Ukaib97be672015-07-02 15:12:48 +0900288 err := v.Eval(&buf, ev)
289 if err != nil {
290 return err
291 }
292 b := buf.Bytes()
Fumitoshi Ukai201df422015-07-07 17:31:05 +0900293 if ast.isRule {
294 abuf.Write(b)
295 continue
296 }
Fumitoshi Ukai6addc2f2015-07-22 11:33:35 +0900297 eq := findLiteralChar(b, '=', 0, skipVar)
Fumitoshi Ukaib97be672015-07-02 15:12:48 +0900298 if eq >= 0 {
299 abuf.Write(b[:eq+1])
Fumitoshi Ukaib97be672015-07-02 15:12:48 +0900300 if eq+1 < len(b) {
301 rhs = append(rhs, tmpval(trimLeftSpaceBytes(b[eq+1:])))
302 }
303 if i+1 < len(aexpr) {
304 rhs = append(rhs, aexpr[i+1:]...)
305 }
306 if ast.semi != nil {
307 rhs = append(rhs, literal(';'))
308 sexpr, _, err := parseExpr(ast.semi, nil, parseOp{})
309 if err != nil {
310 return err
311 }
312 rhs = append(rhs, toExpr(sexpr)...)
313 semi = nil
314 }
315 break
316 }
317 abuf.Write(b)
Fumitoshi Ukai66c4ee12015-07-28 16:31:58 +0900318 if hashFound {
319 break
320 }
Fumitoshi Ukai5c04ad82015-06-18 16:14:04 +0900321 }
Shinichiro Hamaji04932612015-03-31 23:46:56 +0900322
Fumitoshi Ukaib97be672015-07-02 15:12:48 +0900323 line := abuf.Bytes()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900324 r := &rule{srcpos: ast.srcpos}
Fumitoshi Ukai6addc2f2015-07-22 11:33:35 +0900325 if glog.V(1) {
326 glog.Infof("rule? %s: %q assign:%v rhs:%s", r.srcpos, line, ast.assign, rhs)
327 }
Fumitoshi Ukai201df422015-07-07 17:31:05 +0900328 assign, err := r.parse(line, ast.assign, rhs)
Fumitoshi Ukai953ce6f2015-04-04 00:38:53 +0900329 if err != nil {
Fumitoshi Ukaif5b916d2015-07-15 15:57:19 +0900330 ws := newWordScanner(line)
331 if ws.Scan() {
332 if string(ws.Bytes()) == "override" {
Fumitoshi Ukai1ed94372015-07-15 16:28:20 +0900333 warnNoPrefix(ast.srcpos, "invalid `override' directive")
Fumitoshi Ukaif5b916d2015-07-15 15:57:19 +0900334 return nil
335 }
336 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900337 return ast.error(err)
Shinichiro Hamaji21a9b5f2015-04-01 02:42:59 +0900338 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900339 abuf.release()
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900340 if glog.V(1) {
341 glog.Infof("rule %q assign:%v rhs:%v=> outputs:%q, inputs:%q", ast.expr, ast.assign, rhs, r.outputs, r.inputs)
Fumitoshi Ukai5c04ad82015-06-18 16:14:04 +0900342 }
Shinichiro Hamajide829712015-03-31 18:26:56 +0900343
Shinichiro Hamaji04932612015-03-31 23:46:56 +0900344 // TODO: Pretty print.
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900345 // glog.V(1).Infof("RULE: %s=%s (%d commands)", lhs, rhs, len(cmds))
Shinichiro Hamaji04932612015-03-31 23:46:56 +0900346
Fumitoshi Ukai953ce6f2015-04-04 00:38:53 +0900347 if assign != nil {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900348 glog.V(1).Infof("target specific var: %#v", assign)
Fumitoshi Ukaiadc14442015-06-25 16:10:30 +0900349 for _, output := range r.outputs {
Shinichiro Hamajia485d2f2015-04-16 14:03:24 +0900350 ev.setTargetSpecificVar(assign, output)
Shinichiro Hamaji6cc5c612015-04-15 12:59:40 +0900351 }
Fumitoshi Ukaiadc14442015-06-25 16:10:30 +0900352 for _, output := range r.outputPatterns {
Fumitoshi Ukai935de962015-04-28 17:08:20 +0900353 ev.setTargetSpecificVar(assign, output.String())
Shinichiro Hamajiea170b12015-04-15 10:02:33 +0900354 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900355 return nil
Fumitoshi Ukai953ce6f2015-04-04 00:38:53 +0900356 }
Shinichiro Hamajia485d2f2015-04-16 14:03:24 +0900357
Fumitoshi Ukaib97be672015-07-02 15:12:48 +0900358 if semi != nil {
359 r.cmds = append(r.cmds, string(semi))
Shinichiro Hamajia485d2f2015-04-16 14:03:24 +0900360 }
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900361 if glog.V(1) {
362 glog.Infof("rule outputs:%q cmds:%q", r.outputs, r.cmds)
Fumitoshi Ukai5c04ad82015-06-18 16:14:04 +0900363 }
Fumitoshi Ukaiadc14442015-06-25 16:10:30 +0900364 ev.lastRule = r
365 ev.outRules = append(ev.outRules, r)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900366 return nil
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900367}
368
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900369func (ev *Evaluator) evalCommand(ast *commandAST) error {
370 ev.srcpos = ast.srcpos
Fumitoshi Ukaib97be672015-07-02 15:12:48 +0900371 if ev.lastRule == nil || ev.lastRule.outputs == nil {
Shinichiro Hamajib0e81162015-04-09 07:50:06 +0900372 // This could still be an assignment statement. See
373 // assign_after_tab.mk.
374 if strings.IndexByte(ast.cmd, '=') >= 0 {
Shinichiro Hamajic88618f2015-04-11 19:58:06 +0900375 line := trimLeftSpace(ast.cmd)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900376 mk, err := parseMakefileString(line, ast.srcpos)
Shinichiro Hamajib0e81162015-04-09 07:50:06 +0900377 if err != nil {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900378 return ast.errorf("parse failed: %q: %v", line, err)
Shinichiro Hamajib0e81162015-04-09 07:50:06 +0900379 }
Fumitoshi Ukaibcb3b4b2015-07-07 18:00:13 +0900380 if len(mk.stmts) >= 1 && mk.stmts[len(mk.stmts)-1].(*assignAST) != nil {
381 for _, stmt := range mk.stmts {
382 err = ev.eval(stmt)
383 if err != nil {
384 return err
385 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900386 }
Shinichiro Hamajib0e81162015-04-09 07:50:06 +0900387 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900388 return nil
Shinichiro Hamajib0e81162015-04-09 07:50:06 +0900389 }
Shinichiro Hamaji0b2929a2015-05-28 16:31:10 +0900390 // Or, a comment is OK.
391 if strings.TrimSpace(ast.cmd)[0] == '#' {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900392 return nil
Shinichiro Hamaji0b2929a2015-05-28 16:31:10 +0900393 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900394 return ast.errorf("*** commands commence before first target.")
Shinichiro Hamaji0b93c862015-04-07 06:15:15 +0900395 }
396 ev.lastRule.cmds = append(ev.lastRule.cmds, ast.cmd)
397 if ev.lastRule.cmdLineno == 0 {
398 ev.lastRule.cmdLineno = ast.lineno
399 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900400 return nil
Shinichiro Hamaji0b93c862015-04-07 06:15:15 +0900401}
402
Fumitoshi Ukai612e0862015-08-10 16:09:09 +0900403func (ev *Evaluator) paramVar(name string) (Var, error) {
404 idx, err := strconv.ParseInt(name, 10, 32)
405 if err != nil {
406 return nil, fmt.Errorf("param: %s: %v", name, err)
407 }
408 i := int(idx)
409 if i < 0 || i >= len(ev.paramVars) {
410 return nil, fmt.Errorf("param: %s out of %d", name, len(ev.paramVars))
411 }
412 return &automaticVar{value: []byte(ev.paramVars[i])}, nil
413}
414
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900415// LookupVar looks up named variable.
Fumitoshi Ukai8edcb792015-04-02 11:23:23 +0900416func (ev *Evaluator) LookupVar(name string) Var {
Shinichiro Hamajia485d2f2015-04-16 14:03:24 +0900417 if ev.currentScope != nil {
418 v := ev.currentScope.Lookup(name)
419 if v.IsDefined() {
420 return v
421 }
422 }
423 v := ev.outVars.Lookup(name)
424 if v.IsDefined() {
425 return v
426 }
Fumitoshi Ukai612e0862015-08-10 16:09:09 +0900427 v, err := ev.paramVar(name)
428 if err == nil {
429 return v
430 }
Shinichiro Hamajia485d2f2015-04-16 14:03:24 +0900431 return ev.vars.Lookup(name)
432}
433
Fumitoshi Ukaia483ec02015-06-26 10:12:02 +0900434func (ev *Evaluator) lookupVarInCurrentScope(name string) Var {
Shinichiro Hamajia485d2f2015-04-16 14:03:24 +0900435 if ev.currentScope != nil {
436 v := ev.currentScope.Lookup(name)
437 return v
438 }
Fumitoshi Ukai8edcb792015-04-02 11:23:23 +0900439 v := ev.outVars.Lookup(name)
440 if v.IsDefined() {
441 return v
Shinichiro Hamaji69b7f652015-03-31 01:01:59 +0900442 }
Fumitoshi Ukai612e0862015-08-10 16:09:09 +0900443 v, err := ev.paramVar(name)
444 if err == nil {
445 return v
446 }
Fumitoshi Ukai8edcb792015-04-02 11:23:23 +0900447 return ev.vars.Lookup(name)
Shinichiro Hamaji69b7f652015-03-31 01:01:59 +0900448}
449
Fumitoshi Ukai936de102015-06-08 11:21:16 +0900450// EvaluateVar evaluates variable named name.
Shinichiro Hamaji30a02ad2015-05-29 14:56:43 +0900451// Only for a few special uses such as getting SHELL and handling
452// export/unexport.
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900453func (ev *Evaluator) EvaluateVar(name string) (string, error) {
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900454 var buf evalBuffer
455 buf.resetSep()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900456 err := ev.LookupVar(name).Eval(&buf, ev)
457 if err != nil {
458 return "", err
459 }
460 return buf.String(), nil
Shinichiro Hamaji30a02ad2015-05-29 14:56:43 +0900461}
462
Fumitoshi Ukai08eda652015-06-25 16:27:10 +0900463func (ev *Evaluator) evalIncludeFile(fname string, mk makefile) error {
Fumitoshi Ukai83410132015-06-15 14:50:07 +0900464 te := traceEvent.begin("include", literal(fname), traceEventMain)
Fumitoshi Ukai47f401f2015-04-30 17:29:50 +0900465 defer func() {
Fumitoshi Ukai432a2422015-06-11 15:16:29 +0900466 traceEvent.end(te)
Fumitoshi Ukai47f401f2015-04-30 17:29:50 +0900467 }()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900468 var err error
Fumitoshi Ukai47f401f2015-04-30 17:29:50 +0900469 makefileList := ev.outVars.Lookup("MAKEFILE_LIST")
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900470 makefileList, err = makefileList.Append(ev, mk.filename)
471 if err != nil {
472 return err
473 }
Fumitoshi Ukai47f401f2015-04-30 17:29:50 +0900474 ev.outVars.Assign("MAKEFILE_LIST", makefileList)
475
476 for _, stmt := range mk.stmts {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900477 err = ev.eval(stmt)
478 if err != nil {
479 return err
480 }
Fumitoshi Ukai47f401f2015-04-30 17:29:50 +0900481 }
482 return nil
483}
484
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900485func (ev *Evaluator) evalInclude(ast *includeAST) error {
Shinichiro Hamaji0b93c862015-04-07 06:15:15 +0900486 ev.lastRule = nil
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900487 ev.srcpos = ast.srcpos
Shinichiro Hamajid7bef602015-03-30 19:55:32 +0900488
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900489 glog.Infof("%s include %q", ev.srcpos, ast.expr)
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900490 v, _, err := parseExpr([]byte(ast.expr), nil, parseOp{})
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900491 if err != nil {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900492 return ast.errorf("parse failed: %q: %v", ast.expr, err)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900493 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900494 var buf evalBuffer
495 buf.resetSep()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900496 err = v.Eval(&buf, ev)
497 if err != nil {
498 return ast.errorf("%v", err)
499 }
Shinichiro Hamaji2450bfa2015-05-29 16:43:28 +0900500 pats := splitSpaces(buf.String())
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900501 buf.Reset()
Shinichiro Hamaji3e718462015-05-29 17:03:12 +0900502
503 var files []string
Shinichiro Hamaji2450bfa2015-05-29 16:43:28 +0900504 for _, pat := range pats {
Shinichiro Hamaji3e718462015-05-29 17:03:12 +0900505 if strings.Contains(pat, "*") || strings.Contains(pat, "?") {
506 matched, err := filepath.Glob(pat)
Shinichiro Hamaji2450bfa2015-05-29 16:43:28 +0900507 if err != nil {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900508 return ast.errorf("glob error: %s: %v", pat, err)
Shinichiro Hamaji2450bfa2015-05-29 16:43:28 +0900509 }
Shinichiro Hamaji3e718462015-05-29 17:03:12 +0900510 files = append(files, matched...)
511 } else {
512 files = append(files, pat)
513 }
514 }
515
516 for _, fn := range files {
Shinichiro Hamajid9533322015-06-27 05:48:38 +0900517 fn = trimLeadingCurdir(fn)
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900518 if IgnoreOptionalInclude != "" && ast.op == "-include" && matchPattern(fn, IgnoreOptionalInclude) {
Shinichiro Hamaji781a4652015-06-02 16:23:50 +0900519 continue
520 }
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900521 mk, hash, err := makefileCache.parse(fn)
522 if os.IsNotExist(err) {
Shinichiro Hamaji3e718462015-05-29 17:03:12 +0900523 if ast.op == "include" {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900524 return ev.errorf("%v\nNOTE: kati does not support generating missing makefiles", err)
Shinichiro Hamaji3e718462015-05-29 17:03:12 +0900525 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900526 msg := ev.cache.update(fn, hash, fileNotExists)
527 if msg != "" {
528 warn(ev.srcpos, "%s", msg)
529 }
530 continue
Shinichiro Hamaji3e718462015-05-29 17:03:12 +0900531 }
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900532 msg := ev.cache.update(fn, hash, fileExists)
533 if msg != "" {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900534 warn(ev.srcpos, "%s", msg)
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900535 }
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900536 err = ev.evalIncludeFile(fn, mk)
Shinichiro Hamaji3e718462015-05-29 17:03:12 +0900537 if err != nil {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900538 return err
Shinichiro Hamaji2450bfa2015-05-29 16:43:28 +0900539 }
Shinichiro Hamajid7bef602015-03-30 19:55:32 +0900540 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900541 return nil
Shinichiro Hamajid7bef602015-03-30 19:55:32 +0900542}
543
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900544func (ev *Evaluator) evalIf(iast *ifAST) error {
Shinichiro Hamajiaf1e8162015-03-31 02:15:37 +0900545 var isTrue bool
Fumitoshi Ukai91ed5d72015-06-25 13:08:09 +0900546 switch iast.op {
Shinichiro Hamaji497754d2015-03-31 02:02:11 +0900547 case "ifdef", "ifndef":
Fumitoshi Ukai91ed5d72015-06-25 13:08:09 +0900548 expr := iast.lhs
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900549 buf := newEbuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900550 err := expr.Eval(buf, ev)
551 if err != nil {
552 return iast.errorf("%v\n expr:%s", err, expr)
553 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900554 v := ev.LookupVar(buf.String())
555 buf.Reset()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900556 err = v.Eval(buf, ev)
557 if err != nil {
558 return iast.errorf("%v\n expr:%s=>%s", err, expr, v)
559 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900560 value := buf.String()
561 val := buf.Len()
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900562 buf.release()
Fumitoshi Ukai91ed5d72015-06-25 13:08:09 +0900563 isTrue = (val > 0) == (iast.op == "ifdef")
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900564 if glog.V(1) {
565 glog.Infof("%s lhs=%q value=%q => %t", iast.op, iast.lhs, value, isTrue)
Fumitoshi Ukai5c04ad82015-06-18 16:14:04 +0900566 }
Shinichiro Hamaji497754d2015-03-31 02:02:11 +0900567 case "ifeq", "ifneq":
Fumitoshi Ukai91ed5d72015-06-25 13:08:09 +0900568 lexpr := iast.lhs
569 rexpr := iast.rhs
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900570 buf := newEbuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900571 params, err := ev.args(buf, lexpr, rexpr)
572 if err != nil {
573 return iast.errorf("%v\n (%s,%s)", err, lexpr, rexpr)
574 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900575 lhs := string(params[0])
576 rhs := string(params[1])
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900577 buf.release()
Fumitoshi Ukai91ed5d72015-06-25 13:08:09 +0900578 isTrue = (lhs == rhs) == (iast.op == "ifeq")
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900579 if glog.V(1) {
580 glog.Infof("%s lhs=%q %q rhs=%q %q => %t", iast.op, iast.lhs, lhs, iast.rhs, rhs, isTrue)
Fumitoshi Ukai5c04ad82015-06-18 16:14:04 +0900581 }
Shinichiro Hamaji497754d2015-03-31 02:02:11 +0900582 default:
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900583 return iast.errorf("unknown if statement: %q", iast.op)
Shinichiro Hamaji497754d2015-03-31 02:02:11 +0900584 }
Shinichiro Hamajiaf1e8162015-03-31 02:15:37 +0900585
Fumitoshi Ukai91ed5d72015-06-25 13:08:09 +0900586 var stmts []ast
Shinichiro Hamajiaf1e8162015-03-31 02:15:37 +0900587 if isTrue {
Fumitoshi Ukai91ed5d72015-06-25 13:08:09 +0900588 stmts = iast.trueStmts
Shinichiro Hamajiaf1e8162015-03-31 02:15:37 +0900589 } else {
Fumitoshi Ukai91ed5d72015-06-25 13:08:09 +0900590 stmts = iast.falseStmts
Shinichiro Hamajiaf1e8162015-03-31 02:15:37 +0900591 }
Shinichiro Hamaji497754d2015-03-31 02:02:11 +0900592 for _, stmt := range stmts {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900593 err := ev.eval(stmt)
594 if err != nil {
595 return err
596 }
Shinichiro Hamaji497754d2015-03-31 02:02:11 +0900597 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900598 return nil
Shinichiro Hamaji497754d2015-03-31 02:02:11 +0900599}
600
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900601func (ev *Evaluator) evalExport(ast *exportAST) error {
Shinichiro Hamajif61033d2015-05-29 15:01:48 +0900602 ev.lastRule = nil
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900603 ev.srcpos = ast.srcpos
Shinichiro Hamajif61033d2015-05-29 15:01:48 +0900604
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900605 v, _, err := parseExpr(ast.expr, nil, parseOp{})
Shinichiro Hamajif61033d2015-05-29 15:01:48 +0900606 if err != nil {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900607 return ast.errorf("failed to parse: %q: %v", string(ast.expr), err)
Shinichiro Hamajif61033d2015-05-29 15:01:48 +0900608 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900609 var buf evalBuffer
610 buf.resetSep()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900611 err = v.Eval(&buf, ev)
612 if err != nil {
613 return ast.errorf("%v\n expr:%s", err, v)
614 }
Fumitoshi Ukaif5b916d2015-07-15 15:57:19 +0900615 if ast.hasEqual {
616 ev.exports[string(trimSpaceBytes(buf.Bytes()))] = ast.export
617 } else {
618 for _, n := range splitSpacesBytes(buf.Bytes()) {
619 ev.exports[string(n)] = ast.export
620 }
Shinichiro Hamajif61033d2015-05-29 15:01:48 +0900621 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900622 return nil
Shinichiro Hamaji7e521422015-05-29 14:23:30 +0900623}
624
Fumitoshi Ukai09fcd522015-07-15 14:31:50 +0900625func (ev *Evaluator) evalVpath(ast *vpathAST) error {
626 ev.lastRule = nil
627 ev.srcpos = ast.srcpos
628
629 var ebuf evalBuffer
630 ebuf.resetSep()
631 err := ast.expr.Eval(&ebuf, ev)
632 if err != nil {
633 return ast.errorf("%v\n expr:%s", err, ast.expr)
634 }
635 ws := newWordScanner(ebuf.Bytes())
636 if !ws.Scan() {
637 ev.vpaths = nil
638 return nil
639 }
640 pat := string(ws.Bytes())
641 if !ws.Scan() {
642 vpaths := ev.vpaths
643 ev.vpaths = nil
644 for _, v := range vpaths {
645 if v.pattern == pat {
646 continue
647 }
648 ev.vpaths = append(ev.vpaths, v)
649 }
650 return nil
651 }
652 // The search path, DIRECTORIES, is a list of directories to be
653 // searched, separated by colons (semi-colons on MS-DOS and
654 // MS-Windows) or blanks, just like the search path used in the
655 // `VPATH' variable.
656 var dirs []string
657 for {
658 for _, dir := range bytes.Split(ws.Bytes(), []byte{':'}) {
659 dirs = append(dirs, string(dir))
660 }
661 if !ws.Scan() {
662 break
663 }
664 }
665 ev.vpaths = append(ev.vpaths, vpath{
666 pattern: pat,
667 dirs: dirs,
668 })
669 return nil
670}
671
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900672func (ev *Evaluator) eval(stmt ast) error {
673 return stmt.eval(ev)
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900674}
675
Fumitoshi Ukai08eda652015-06-25 16:27:10 +0900676func eval(mk makefile, vars Vars, useCache bool) (er *evalResult, err error) {
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900677 ev := NewEvaluator(vars)
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900678 if useCache {
679 ev.cache = newAccessCache()
680 }
Shinichiro Hamaji491e73f2015-04-07 12:41:59 +0900681
Fumitoshi Ukai936de102015-06-08 11:21:16 +0900682 makefileList := vars.Lookup("MAKEFILE_LIST")
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900683 if !makefileList.IsDefined() {
Fumitoshi Ukai7655f182015-07-15 14:05:41 +0900684 makefileList = &simpleVar{value: []string{""}, origin: "file"}
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900685 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900686 makefileList, err = makefileList.Append(ev, mk.filename)
687 if err != nil {
688 return nil, err
689 }
Fumitoshi Ukai936de102015-06-08 11:21:16 +0900690 ev.outVars.Assign("MAKEFILE_LIST", makefileList)
Shinichiro Hamaji491e73f2015-04-07 12:41:59 +0900691
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900692 for _, stmt := range mk.stmts {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900693 err = ev.eval(stmt)
694 if err != nil {
695 return nil, err
696 }
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900697 }
Shinichiro Hamaji750ae2e2015-05-20 12:59:15 +0900698
Fumitoshi Ukai09fcd522015-07-15 14:31:50 +0900699 vpaths := searchPaths{
700 vpaths: ev.vpaths,
701 }
702 v, found := ev.outVars["VPATH"]
703 if found {
704 wb := newWbuf()
705 err := v.Eval(wb, ev)
706 if err != nil {
707 return nil, err
708 }
709 // In the 'VPATH' variable, directory names are separated
710 // by colons or blanks. (on windows, semi-colons)
711 for _, word := range wb.words {
712 for _, dir := range bytes.Split(word, []byte{':'}) {
713 vpaths.dirs = append(vpaths.dirs, string(dir))
714 }
715 }
716 }
717 glog.Infof("vpaths: %#v", vpaths)
718
Fumitoshi Ukai08eda652015-06-25 16:27:10 +0900719 return &evalResult{
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900720 vars: ev.outVars,
721 rules: ev.outRules,
722 ruleVars: ev.outRuleVars,
723 accessedMks: ev.cache.Slice(),
724 exports: ev.exports,
Fumitoshi Ukai09fcd522015-07-15 14:31:50 +0900725 vpaths: vpaths,
Fumitoshi Ukaif8efa0a2015-03-30 18:10:11 +0900726 }, nil
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900727}