1// 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
15package kati
16
17import (
18	"bytes"
19	"fmt"
20	"io"
21	"strings"
22)
23
24// Var is an interface of make variable.
25type Var interface {
26	Value
27	Append(*Evaluator, string) (Var, error)
28	AppendVar(*Evaluator, Value) (Var, error)
29	Flavor() string
30	Origin() string
31	IsDefined() bool
32}
33
34type targetSpecificVar struct {
35	v  Var
36	op string
37}
38
39func (v *targetSpecificVar) Append(ev *Evaluator, s string) (Var, error) {
40	nv, err := v.v.Append(ev, s)
41	if err != nil {
42		return nil, err
43	}
44	return &targetSpecificVar{
45		v:  nv,
46		op: v.op,
47	}, nil
48}
49func (v *targetSpecificVar) AppendVar(ev *Evaluator, v2 Value) (Var, error) {
50	nv, err := v.v.AppendVar(ev, v2)
51	if err != nil {
52		return nil, err
53	}
54	return &targetSpecificVar{
55		v:  nv,
56		op: v.op,
57	}, nil
58}
59func (v *targetSpecificVar) Flavor() string {
60	return v.v.Flavor()
61}
62func (v *targetSpecificVar) Origin() string {
63	return v.v.Origin()
64}
65func (v *targetSpecificVar) IsDefined() bool {
66	return v.v.IsDefined()
67}
68func (v *targetSpecificVar) String() string {
69	// TODO: If we add the info of |op| a test starts
70	// failing. Shouldn't we use this only for debugging?
71	return v.v.String()
72	// return v.v.String() + " (op=" + v.op + ")"
73}
74func (v *targetSpecificVar) Eval(w evalWriter, ev *Evaluator) error {
75	return v.v.Eval(w, ev)
76}
77
78func (v *targetSpecificVar) serialize() serializableVar {
79	return serializableVar{
80		Type:     v.op,
81		Children: []serializableVar{v.v.serialize()},
82	}
83}
84
85func (v *targetSpecificVar) dump(d *dumpbuf) {
86	d.Byte(valueTypeTSV)
87	d.Str(v.op)
88	v.v.dump(d)
89}
90
91type simpleVar struct {
92	// space separated. note that each string may contain spaces, so
93	// it is not word list.
94	value  []string
95	origin string
96}
97
98func (v *simpleVar) Flavor() string  { return "simple" }
99func (v *simpleVar) Origin() string  { return v.origin }
100func (v *simpleVar) IsDefined() bool { return true }
101
102func (v *simpleVar) String() string { return strings.Join(v.value, " ") }
103func (v *simpleVar) Eval(w evalWriter, ev *Evaluator) error {
104	space := false
105	for _, v := range v.value {
106		if space {
107			writeByte(w, ' ')
108		}
109		io.WriteString(w, v)
110		space = true
111	}
112	return nil
113}
114func (v *simpleVar) serialize() serializableVar {
115	return serializableVar{
116		Type:   "simple",
117		V:      v.String(),
118		Origin: v.origin,
119	}
120}
121func (v *simpleVar) dump(d *dumpbuf) {
122	d.Byte(valueTypeSimple)
123	d.Int(len(v.value))
124	for _, v := range v.value {
125		d.Str(v)
126	}
127	d.Str(v.origin)
128}
129
130func (v *simpleVar) Append(ev *Evaluator, s string) (Var, error) {
131	val, _, err := parseExpr([]byte(s), nil, parseOp{})
132	if err != nil {
133		return nil, err
134	}
135	abuf := newEbuf()
136	err = val.Eval(abuf, ev)
137	if err != nil {
138		return nil, err
139	}
140	v.value = append(v.value, abuf.String())
141	abuf.release()
142	return v, nil
143}
144
145func (v *simpleVar) AppendVar(ev *Evaluator, val Value) (Var, error) {
146	abuf := newEbuf()
147	err := val.Eval(abuf, ev)
148	if err != nil {
149		return nil, err
150	}
151	v.value = append(v.value, abuf.String())
152	abuf.release()
153	return v, nil
154}
155
156type automaticVar struct {
157	value []byte
158}
159
160func (v *automaticVar) Flavor() string  { return "simple" }
161func (v *automaticVar) Origin() string  { return "automatic" }
162func (v *automaticVar) IsDefined() bool { return true }
163
164func (v *automaticVar) String() string { return string(v.value) }
165func (v *automaticVar) Eval(w evalWriter, ev *Evaluator) error {
166	w.Write(v.value)
167	return nil
168}
169func (v *automaticVar) serialize() serializableVar {
170	return serializableVar{Type: ""}
171}
172func (v *automaticVar) dump(d *dumpbuf) {
173	d.err = fmt.Errorf("cannnot dump automatic var:%s", v.value)
174}
175
176func (v *automaticVar) Append(ev *Evaluator, s string) (Var, error) {
177	val, _, err := parseExpr([]byte(s), nil, parseOp{})
178	if err != nil {
179		return nil, err
180	}
181	abuf := newEbuf()
182	err = val.Eval(abuf, ev)
183	if err != nil {
184		return nil, err
185	}
186	value := []string{string(v.value), abuf.String()}
187	abuf.release()
188	return &simpleVar{
189		value:  value,
190		origin: "file",
191	}, nil
192}
193
194func (v *automaticVar) AppendVar(ev *Evaluator, val Value) (Var, error) {
195	abuf := newEbuf()
196	err := val.Eval(abuf, ev)
197	if err != nil {
198		return nil, err
199	}
200	value := []string{string(v.value), abuf.String()}
201	abuf.release()
202	return &simpleVar{
203		value:  value,
204		origin: "file",
205	}, nil
206}
207
208type recursiveVar struct {
209	expr   Value
210	origin string
211}
212
213func (v *recursiveVar) Flavor() string  { return "recursive" }
214func (v *recursiveVar) Origin() string  { return v.origin }
215func (v *recursiveVar) IsDefined() bool { return true }
216
217func (v *recursiveVar) String() string { return v.expr.String() }
218func (v *recursiveVar) Eval(w evalWriter, ev *Evaluator) error {
219	v.expr.Eval(w, ev)
220	return nil
221}
222func (v *recursiveVar) serialize() serializableVar {
223	return serializableVar{
224		Type:     "recursive",
225		Children: []serializableVar{v.expr.serialize()},
226		Origin:   v.origin,
227	}
228}
229func (v *recursiveVar) dump(d *dumpbuf) {
230	d.Byte(valueTypeRecursive)
231	v.expr.dump(d)
232	d.Str(v.origin)
233}
234
235func (v *recursiveVar) Append(_ *Evaluator, s string) (Var, error) {
236	var exp expr
237	if e, ok := v.expr.(expr); ok {
238		exp = append(e, literal(" "))
239	} else {
240		exp = expr{v.expr, literal(" ")}
241	}
242	sv, _, err := parseExpr([]byte(s), nil, parseOp{alloc: true})
243	if err != nil {
244		return nil, err
245	}
246	if aexpr, ok := sv.(expr); ok {
247		exp = append(exp, aexpr...)
248	} else {
249		exp = append(exp, sv)
250	}
251	v.expr = exp
252	return v, nil
253}
254
255func (v *recursiveVar) AppendVar(ev *Evaluator, val Value) (Var, error) {
256	var buf bytes.Buffer
257	buf.WriteString(v.expr.String())
258	buf.WriteByte(' ')
259	buf.WriteString(val.String())
260	e, _, err := parseExpr(buf.Bytes(), nil, parseOp{alloc: true})
261	if err != nil {
262		return nil, err
263	}
264	v.expr = e
265	return v, nil
266}
267
268type undefinedVar struct{}
269
270func (undefinedVar) Flavor() string  { return "undefined" }
271func (undefinedVar) Origin() string  { return "undefined" }
272func (undefinedVar) IsDefined() bool { return false }
273func (undefinedVar) String() string  { return "" }
274func (undefinedVar) Eval(_ evalWriter, _ *Evaluator) error {
275	return nil
276}
277func (undefinedVar) serialize() serializableVar {
278	return serializableVar{Type: "undefined"}
279}
280func (undefinedVar) dump(d *dumpbuf) {
281	d.Byte(valueTypeUndefined)
282}
283
284func (undefinedVar) Append(*Evaluator, string) (Var, error) {
285	return undefinedVar{}, nil
286}
287
288func (undefinedVar) AppendVar(_ *Evaluator, val Value) (Var, error) {
289	return undefinedVar{}, nil
290}
291
292// Vars is a map for make variables.
293type Vars map[string]Var
294
295// usedEnvs tracks what environment variables are used.
296var usedEnvs = map[string]bool{}
297
298// Lookup looks up named make variable.
299func (vt Vars) Lookup(name string) Var {
300	if v, ok := vt[name]; ok {
301		if strings.HasPrefix(v.Origin(), "environment") {
302			usedEnvs[name] = true
303		}
304		return v
305	}
306	return undefinedVar{}
307}
308
309// origin precedence
310//  override / environment override
311//  command line
312//  file
313//  environment
314//  default
315// TODO(ukai): is this correct order?
316var originPrecedence = map[string]int{
317	"override":             4,
318	"environment override": 4,
319	"command line":         3,
320	"file":                 2,
321	"environment":          2,
322	"default":              1,
323	"undefined":            0,
324	"automatic":            0,
325}
326
327// Assign assigns v to name.
328func (vt Vars) Assign(name string, v Var) {
329	vo := v.Origin()
330	// assign automatic always win.
331	// assign new value to automatic always win.
332	if vo != "automatic" {
333		vp := originPrecedence[v.Origin()]
334		var op int
335		if ov, ok := vt[name]; ok {
336			op = originPrecedence[ov.Origin()]
337		}
338		if op > vp {
339			return
340		}
341	}
342	vt[name] = v
343}
344
345// NewVars creates new Vars.
346func NewVars(vt Vars) Vars {
347	r := make(Vars)
348	r.Merge(vt)
349	return r
350}
351
352// Merge merges vt2 into vt.
353func (vt Vars) Merge(vt2 Vars) {
354	for k, v := range vt2 {
355		vt[k] = v
356	}
357}
358
359// save saves value of the variable named name.
360// calling returned value will restore to the old value at the time
361// when save called.
362func (vt Vars) save(name string) func() {
363	if v, ok := vt[name]; ok {
364		return func() {
365			vt[name] = v
366		}
367	}
368	return func() {
369		delete(vt, name)
370	}
371}
372