| // 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 main |
| |
| import ( |
| "bytes" |
| "fmt" |
| "io" |
| ) |
| |
| type Var interface { |
| Value |
| Append(*Evaluator, string) Var |
| AppendVar(*Evaluator, Value) Var |
| Flavor() string |
| Origin() string |
| IsDefined() bool |
| } |
| |
| type TargetSpecificVar struct { |
| v Var |
| op string |
| } |
| |
| func (v *TargetSpecificVar) Append(ev *Evaluator, s string) Var { |
| return &TargetSpecificVar{ |
| v: v.v.Append(ev, s), |
| op: v.op, |
| } |
| } |
| func (v *TargetSpecificVar) AppendVar(ev *Evaluator, v2 Value) Var { |
| return &TargetSpecificVar{ |
| v: v.v.AppendVar(ev, v2), |
| op: v.op, |
| } |
| } |
| 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) { |
| v.v.Eval(w, ev) |
| } |
| |
| func (v *TargetSpecificVar) Serialize() SerializableVar { |
| return SerializableVar{ |
| Type: v.op, |
| Children: []SerializableVar{v.v.Serialize()}, |
| } |
| } |
| |
| func (v *TargetSpecificVar) Dump(w io.Writer) { |
| dumpByte(w, ValueTypeTSV) |
| dumpString(w, v.op) |
| v.v.Dump(w) |
| } |
| |
| 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) { |
| io.WriteString(w, v.value) |
| } |
| func (v *SimpleVar) Serialize() SerializableVar { |
| return SerializableVar{ |
| Type: "simple", |
| V: v.value, |
| Origin: v.origin, |
| } |
| } |
| func (v *SimpleVar) Dump(w io.Writer) { |
| dumpByte(w, ValueTypeSimple) |
| dumpString(w, v.value) |
| dumpString(w, v.origin) |
| } |
| |
| func (v *SimpleVar) Append(ev *Evaluator, s string) Var { |
| val, _, err := parseExpr([]byte(s), nil, false) |
| if err != nil { |
| panic(err) |
| } |
| abuf := newBuf() |
| io.WriteString(abuf, v.value) |
| writeByte(abuf, ' ') |
| val.Eval(abuf, ev) |
| v.value = abuf.String() |
| freeBuf(abuf) |
| return v |
| } |
| |
| func (v *SimpleVar) AppendVar(ev *Evaluator, val Value) Var { |
| abuf := newBuf() |
| io.WriteString(abuf, v.value) |
| writeByte(abuf, ' ') |
| val.Eval(abuf, ev) |
| v.value = abuf.String() |
| freeBuf(abuf) |
| return v |
| } |
| |
| 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) { |
| w.Write(v.value) |
| } |
| func (v *AutomaticVar) Serialize() SerializableVar { |
| panic(fmt.Sprintf("cannnot serialize automatic var:%s", v.value)) |
| } |
| func (v *AutomaticVar) Dump(w io.Writer) { |
| panic(fmt.Sprintf("cannnot dump automatic var:%s", v.value)) |
| } |
| |
| func (v *AutomaticVar) Append(ev *Evaluator, s string) Var { |
| val, _, err := parseExpr([]byte(s), nil, false) |
| if err != nil { |
| panic(err) |
| } |
| buf := bytes.NewBuffer(v.value) |
| buf.WriteByte(' ') |
| val.Eval(buf, ev) |
| v.value = buf.Bytes() |
| return v |
| } |
| |
| func (v *AutomaticVar) AppendVar(ev *Evaluator, val Value) Var { |
| buf := bytes.NewBuffer(v.value) |
| buf.WriteByte(' ') |
| val.Eval(buf, ev) |
| v.value = buf.Bytes() |
| return v |
| } |
| |
| 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) { |
| v.expr.Eval(w, ev) |
| } |
| func (v *RecursiveVar) Serialize() SerializableVar { |
| return SerializableVar{ |
| Type: "recursive", |
| Children: []SerializableVar{v.expr.Serialize()}, |
| Origin: v.origin, |
| } |
| } |
| func (v *RecursiveVar) Dump(w io.Writer) { |
| dumpByte(w, ValueTypeRecursive) |
| v.expr.Dump(w) |
| dumpString(w, v.origin) |
| } |
| |
| func (v *RecursiveVar) Append(_ *Evaluator, s string) Var { |
| var expr Expr |
| if e, ok := v.expr.(Expr); ok { |
| expr = append(e, literal(" ")) |
| } else { |
| expr = Expr{v.expr, literal(" ")} |
| } |
| sv, _, err := parseExpr([]byte(s), nil, true) |
| if err != nil { |
| panic(err) |
| } |
| if aexpr, ok := sv.(Expr); ok { |
| expr = append(expr, aexpr...) |
| } else { |
| expr = append(expr, sv) |
| } |
| v.expr = expr |
| return v |
| } |
| |
| func (v *RecursiveVar) AppendVar(ev *Evaluator, val Value) Var { |
| 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 { |
| panic(err) |
| } |
| v.expr = e |
| return v |
| } |
| |
| 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) { |
| } |
| func (UndefinedVar) Serialize() SerializableVar { |
| return SerializableVar{Type: "undefined"} |
| } |
| func (UndefinedVar) Dump(w io.Writer) { |
| dumpByte(w, ValueTypeUndefined) |
| } |
| |
| func (UndefinedVar) Append(*Evaluator, string) Var { |
| return UndefinedVar{} |
| } |
| |
| func (UndefinedVar) AppendVar(_ *Evaluator, val Value) Var { |
| return UndefinedVar{} |
| } |
| |
| type Vars map[string]Var |
| |
| func (vt Vars) Lookup(name string) Var { |
| if v, ok := vt[name]; ok { |
| return v |
| } |
| return UndefinedVar{} |
| } |
| |
| 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 |
| } |
| |
| func NewVars(vt Vars) Vars { |
| r := make(Vars) |
| r.Merge(vt) |
| return r |
| } |
| |
| 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) |
| } |
| } |