// Copyright 2015 Google Inc. All rights reserved // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package kati import ( "bytes" "fmt" "io" ) // Var is an interface of make variable. type Var interface { Value Append(*Evaluator, string) (Var, error) AppendVar(*Evaluator, Value) (Var, error) Flavor() string Origin() string IsDefined() bool } type targetSpecificVar struct { v Var op string } func (v *targetSpecificVar) Append(ev *Evaluator, s string) (Var, error) { nv, err := v.v.Append(ev, s) if err != nil { return nil, err } return &targetSpecificVar{ v: nv, op: v.op, }, nil } func (v *targetSpecificVar) AppendVar(ev *Evaluator, v2 Value) (Var, error) { nv, err := v.v.AppendVar(ev, v2) if err != nil { return nil, err } return &targetSpecificVar{ v: nv, op: v.op, }, nil } func (v *targetSpecificVar) Flavor() string { return v.v.Flavor() } func (v *targetSpecificVar) Origin() string { return v.v.Origin() } func (v *targetSpecificVar) IsDefined() bool { return v.v.IsDefined() } func (v *targetSpecificVar) String() string { // TODO: If we add the info of |op| a test starts // failing. Shouldn't we use this only for debugging? return v.v.String() // return v.v.String() + " (op=" + v.op + ")" } func (v *targetSpecificVar) Eval(w io.Writer, ev *Evaluator) error { return v.v.Eval(w, ev) } func (v *targetSpecificVar) serialize() serializableVar { return serializableVar{ Type: v.op, Children: []serializableVar{v.v.serialize()}, } } func (v *targetSpecificVar) dump(d *dumpbuf) { d.Byte(valueTypeTSV) d.Str(v.op) v.v.dump(d) } type simpleVar struct { value string origin string } func (v *simpleVar) Flavor() string { return "simple" } func (v *simpleVar) Origin() string { return v.origin } func (v *simpleVar) IsDefined() bool { return true } func (v *simpleVar) String() string { return v.value } func (v *simpleVar) Eval(w io.Writer, ev *Evaluator) error { io.WriteString(w, v.value) return nil } func (v *simpleVar) serialize() serializableVar { return serializableVar{ Type: "simple", V: v.value, Origin: v.origin, } } func (v *simpleVar) dump(d *dumpbuf) { d.Byte(valueTypeSimple) d.Str(v.value) d.Str(v.origin) } func (v *simpleVar) Append(ev *Evaluator, s string) (Var, error) { val, _, err := parseExpr([]byte(s), nil, false) if err != nil { return nil, err } abuf := newBuf() io.WriteString(abuf, v.value) writeByte(abuf, ' ') err = val.Eval(abuf, ev) if err != nil { return nil, err } v.value = abuf.String() freeBuf(abuf) return v, nil } func (v *simpleVar) AppendVar(ev *Evaluator, val Value) (Var, error) { abuf := newBuf() io.WriteString(abuf, v.value) writeByte(abuf, ' ') err := val.Eval(abuf, ev) if err != nil { return nil, err } v.value = abuf.String() freeBuf(abuf) return v, nil } type automaticVar struct { value []byte } func (v *automaticVar) Flavor() string { return "simple" } func (v *automaticVar) Origin() string { return "automatic" } func (v *automaticVar) IsDefined() bool { return true } func (v *automaticVar) String() string { return string(v.value) } func (v *automaticVar) Eval(w io.Writer, ev *Evaluator) error { w.Write(v.value) return nil } func (v *automaticVar) serialize() serializableVar { return serializableVar{Type: ""} } func (v *automaticVar) dump(d *dumpbuf) { d.err = fmt.Errorf("cannnot dump automatic var:%s", v.value) } func (v *automaticVar) Append(ev *Evaluator, s string) (Var, error) { val, _, err := parseExpr([]byte(s), nil, false) if err != nil { return nil, err } buf := bytes.NewBuffer(v.value) buf.WriteByte(' ') err = val.Eval(buf, ev) if err != nil { return nil, err } v.value = buf.Bytes() return v, nil } func (v *automaticVar) AppendVar(ev *Evaluator, val Value) (Var, error) { buf := bytes.NewBuffer(v.value) buf.WriteByte(' ') err := val.Eval(buf, ev) if err != nil { return nil, err } v.value = buf.Bytes() return v, nil } type recursiveVar struct { expr Value origin string } func (v *recursiveVar) Flavor() string { return "recursive" } func (v *recursiveVar) Origin() string { return v.origin } func (v *recursiveVar) IsDefined() bool { return true } func (v *recursiveVar) String() string { return v.expr.String() } func (v *recursiveVar) Eval(w io.Writer, ev *Evaluator) error { v.expr.Eval(w, ev) return nil } func (v *recursiveVar) serialize() serializableVar { return serializableVar{ Type: "recursive", Children: []serializableVar{v.expr.serialize()}, Origin: v.origin, } } func (v *recursiveVar) dump(d *dumpbuf) { d.Byte(valueTypeRecursive) v.expr.dump(d) d.Str(v.origin) } func (v *recursiveVar) Append(_ *Evaluator, s string) (Var, error) { var exp expr if e, ok := v.expr.(expr); ok { exp = append(e, literal(" ")) } else { exp = expr{v.expr, literal(" ")} } sv, _, err := parseExpr([]byte(s), nil, true) if err != nil { return nil, err } if aexpr, ok := sv.(expr); ok { exp = append(exp, aexpr...) } else { exp = append(exp, sv) } v.expr = exp return v, nil } func (v *recursiveVar) AppendVar(ev *Evaluator, val Value) (Var, error) { var buf bytes.Buffer buf.WriteString(v.expr.String()) buf.WriteByte(' ') buf.WriteString(val.String()) e, _, err := parseExpr(buf.Bytes(), nil, true) if err != nil { return nil, err } v.expr = e return v, nil } type undefinedVar struct{} func (undefinedVar) Flavor() string { return "undefined" } func (undefinedVar) Origin() string { return "undefined" } func (undefinedVar) IsDefined() bool { return false } func (undefinedVar) String() string { return "" } func (undefinedVar) Eval(_ io.Writer, _ *Evaluator) error { return nil } func (undefinedVar) serialize() serializableVar { return serializableVar{Type: "undefined"} } func (undefinedVar) dump(d *dumpbuf) { d.Byte(valueTypeUndefined) } func (undefinedVar) Append(*Evaluator, string) (Var, error) { return undefinedVar{}, nil } func (undefinedVar) AppendVar(_ *Evaluator, val Value) (Var, error) { return undefinedVar{}, nil } // Vars is a map for make variables. type Vars map[string]Var // Lookup looks up named make variable. func (vt Vars) Lookup(name string) Var { if v, ok := vt[name]; ok { return v } return undefinedVar{} } // Assign assigns v to name. func (vt Vars) Assign(name string, v Var) { switch v.Origin() { case "override", "environment override": default: if ov, ok := vt[name]; ok { if ov.Origin() == "command line" { return } } } vt[name] = v } // NewVars creates new Vars. func NewVars(vt Vars) Vars { r := make(Vars) r.Merge(vt) return r } // Merge merges vt2 into vt. func (vt Vars) Merge(vt2 Vars) { for k, v := range vt2 { vt[k] = v } } // save saves value of the variable named name. // calling returned value will restore to the old value at the time // when save called. func (vt Vars) save(name string) func() { if v, ok := vt[name]; ok { return func() { vt[name] = v } } return func() { delete(vt, name) } }