aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ast.go4
-rw-r--r--buf.go210
-rw-r--r--buf_test.go (renamed from ioutil_test.go)0
-rw-r--r--eval.go36
-rw-r--r--evalcmd.go4
-rw-r--r--expr.go12
-rw-r--r--fileutil.go5
-rw-r--r--func.go217
-rw-r--r--func_test.go6
-rw-r--r--ioutil.go147
-rw-r--r--shellutil.go36
-rw-r--r--var.go16
12 files changed, 392 insertions, 301 deletions
diff --git a/ast.go b/ast.go
index 0831ec1..ff5c833 100644
--- a/ast.go
+++ b/ast.go
@@ -50,8 +50,8 @@ func (ast *assignAST) evalRHS(ev *Evaluator, lhs string) (Var, error) {
case tmpval:
return &simpleVar{value: v.String(), origin: origin}, nil
default:
- var buf buffer
- buf.resetSpace()
+ var buf evalBuffer
+ buf.resetSep()
err := v.Eval(&buf, ev)
if err != nil {
return nil, err
diff --git a/buf.go b/buf.go
new file mode 100644
index 0000000..737e7c9
--- /dev/null
+++ b/buf.go
@@ -0,0 +1,210 @@
+// 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 (
+ "io"
+ "sync"
+)
+
+var (
+ ebufFree = sync.Pool{
+ New: func() interface{} { return new(evalBuffer) },
+ }
+ wbufFree = sync.Pool{
+ New: func() interface{} { return new(wordBuffer) },
+ }
+)
+
+func writeByte(w io.Writer, b byte) error {
+ if bw, ok := w.(io.ByteWriter); ok {
+ return bw.WriteByte(b)
+ }
+ _, err := w.Write([]byte{b})
+ return err
+}
+
+// use io.WriteString to stringWrite.
+
+type ssvWriter struct {
+ io.Writer
+ sep bool
+}
+
+func (w *ssvWriter) writeWord(word []byte) {
+ if w.sep {
+ writeByte(w.Writer, ' ')
+ }
+ w.sep = true
+ w.Writer.Write(word)
+}
+
+func (w *ssvWriter) writeWordString(word string) {
+ if w.sep {
+ writeByte(w.Writer, ' ')
+ }
+ w.sep = true
+ io.WriteString(w.Writer, word)
+}
+
+func (w *ssvWriter) resetSep() {
+ w.sep = false
+}
+
+type buffer struct {
+ buf []byte
+ bootstrap [64]byte // memory to hold first slice
+}
+
+func (b *buffer) Write(data []byte) (int, error) {
+ b.buf = append(b.buf, data...)
+ return len(data), nil
+}
+
+func (b *buffer) WriteByte(c byte) error {
+ b.buf = append(b.buf, c)
+ return nil
+}
+
+func (b *buffer) WriteString(s string) (int, error) {
+ b.buf = append(b.buf, []byte(s)...)
+ return len(s), nil
+}
+
+func (b *buffer) Bytes() []byte { return b.buf }
+func (b *buffer) Len() int { return len(b.buf) }
+func (b *buffer) String() string { return string(b.buf) }
+
+func (b *buffer) Reset() {
+ if b.buf == nil {
+ b.buf = b.bootstrap[:0]
+ }
+ b.buf = b.buf[:0]
+}
+
+type evalBuffer struct {
+ buffer
+ ssvWriter
+ args [][]byte
+}
+
+func newEbuf() *evalBuffer {
+ buf := ebufFree.Get().(*evalBuffer)
+ buf.Reset()
+ return buf
+}
+
+func (buf *evalBuffer) release() {
+ if cap(buf.Bytes()) > 1024 {
+ return
+ }
+ buf.Reset()
+ buf.args = buf.args[:0]
+ ebufFree.Put(buf)
+}
+
+func (b *evalBuffer) Reset() {
+ b.buffer.Reset()
+ b.resetSep()
+}
+
+func (b *evalBuffer) resetSep() {
+ if b.ssvWriter.Writer == nil {
+ b.ssvWriter.Writer = &b.buffer
+ }
+ b.ssvWriter.resetSep()
+}
+
+type wordBuffer struct {
+ buf buffer
+ words [][]byte
+}
+
+func newWbuf() *wordBuffer {
+ buf := wbufFree.Get().(*wordBuffer)
+ buf.Reset()
+ return buf
+}
+
+func (buf *wordBuffer) release() {
+ if cap(buf.Bytes()) > 1024 {
+ return
+ }
+ buf.Reset()
+ wbufFree.Put(buf)
+}
+
+func (wb *wordBuffer) Write(data []byte) (int, error) {
+ if len(data) == 0 {
+ return 0, nil
+ }
+ off := len(wb.buf.buf)
+ var cont bool
+ if !isWhitespace(rune(data[0])) && len(wb.buf.buf) > 0 {
+ cont = !isWhitespace(rune(wb.buf.buf[off-1]))
+ }
+ ws := newWordScanner(data)
+ for ws.Scan() {
+ if cont {
+ word := wb.words[len(wb.words)-1]
+ wb.words = wb.words[:len(wb.words)-1]
+ wb.buf.buf = wb.buf.buf[:len(wb.buf.buf)-len(word)]
+ var w []byte
+ w = append(w, word...)
+ w = append(w, ws.Bytes()...)
+ wb.writeWord(w)
+ cont = false
+ continue
+ }
+ wb.writeWord(ws.Bytes())
+ }
+ if isWhitespace(rune(data[len(data)-1])) {
+ wb.buf.buf = append(wb.buf.buf, ' ')
+ }
+ return len(data), nil
+}
+
+func (wb *wordBuffer) WriteByte(c byte) error {
+ _, err := wb.Write([]byte{c})
+ return err
+}
+
+func (wb *wordBuffer) WriteString(s string) (int, error) {
+ return wb.Write([]byte(s))
+}
+
+func (wb *wordBuffer) writeWord(word []byte) {
+ if len(wb.buf.buf) > 0 {
+ wb.buf.buf = append(wb.buf.buf, ' ')
+ }
+ off := len(wb.buf.buf)
+ wb.buf.buf = append(wb.buf.buf, word...)
+ wb.words = append(wb.words, wb.buf.buf[off:off+len(word)])
+}
+
+func (wb *wordBuffer) writeWordString(word string) {
+ wb.writeWord([]byte(word))
+}
+
+func (wb *wordBuffer) Reset() {
+ wb.buf.Reset()
+ wb.words = nil
+}
+
+func (wb *wordBuffer) resetSep() {}
+
+func (wb *wordBuffer) Bytes() []byte {
+ return wb.buf.Bytes()
+}
diff --git a/ioutil_test.go b/buf_test.go
index 8ee14a0..8ee14a0 100644
--- a/ioutil_test.go
+++ b/buf_test.go
diff --git a/eval.go b/eval.go
index 16452ba..00c9ee7 100644
--- a/eval.go
+++ b/eval.go
@@ -171,10 +171,10 @@ func NewEvaluator(vars map[string]Var) *Evaluator {
}
}
-func (ev *Evaluator) args(buf *buffer, args ...Value) ([][]byte, error) {
+func (ev *Evaluator) args(buf *evalBuffer, args ...Value) ([][]byte, error) {
pos := make([]int, 0, len(args))
for _, arg := range args {
- buf.resetSpace()
+ buf.resetSep()
err := arg.Eval(buf, ev)
if err != nil {
return nil, err
@@ -217,13 +217,13 @@ func (ev *Evaluator) evalAssignAST(ast *assignAST) (string, Var, error) {
case tmpval:
lhs = string(v)
default:
- buf := newBuf()
+ buf := newEbuf()
err := v.Eval(buf, ev)
if err != nil {
return "", nil, err
}
lhs = string(trimSpaceBytes(buf.Bytes()))
- freeBuf(buf)
+ buf.release()
}
rhs, err := ast.evalRHS(ev, lhs)
if err != nil {
@@ -257,13 +257,13 @@ func (ev *Evaluator) evalMaybeRule(ast *maybeRuleAST) error {
logf("maybe rule %s: %q assign:%v", ev.srcpos, ast.expr, ast.assign)
- abuf := newBuf()
+ abuf := newEbuf()
aexpr := toExpr(ast.expr)
var rhs expr
semi := ast.semi
for i, v := range aexpr {
- var buf buffer
- buf.resetSpace()
+ var buf evalBuffer
+ buf.resetSep()
err := v.Eval(&buf, ev)
if err != nil {
return err
@@ -302,7 +302,7 @@ func (ev *Evaluator) evalMaybeRule(ast *maybeRuleAST) error {
if err != nil {
return ast.error(err)
}
- freeBuf(abuf)
+ abuf.release()
if LogFlag {
logf("rule %q assign:%v rhs:%v=> outputs:%q, inputs:%q", ast.expr, ast.assign, rhs, r.outputs, r.inputs)
}
@@ -397,8 +397,8 @@ func (ev *Evaluator) lookupVarInCurrentScope(name string) Var {
// Only for a few special uses such as getting SHELL and handling
// export/unexport.
func (ev *Evaluator) EvaluateVar(name string) (string, error) {
- var buf buffer
- buf.resetSpace()
+ var buf evalBuffer
+ buf.resetSep()
err := ev.LookupVar(name).Eval(&buf, ev)
if err != nil {
return "", err
@@ -437,8 +437,8 @@ func (ev *Evaluator) evalInclude(ast *includeAST) error {
if err != nil {
return ast.errorf("parse failed: %q: %v", ast.expr, err)
}
- var buf buffer
- buf.resetSpace()
+ var buf evalBuffer
+ buf.resetSep()
err = v.Eval(&buf, ev)
if err != nil {
return ast.errorf("%v", err)
@@ -492,7 +492,7 @@ func (ev *Evaluator) evalIf(iast *ifAST) error {
switch iast.op {
case "ifdef", "ifndef":
expr := iast.lhs
- buf := newBuf()
+ buf := newEbuf()
err := expr.Eval(buf, ev)
if err != nil {
return iast.errorf("%v\n expr:%s", err, expr)
@@ -505,7 +505,7 @@ func (ev *Evaluator) evalIf(iast *ifAST) error {
}
value := buf.String()
val := buf.Len()
- freeBuf(buf)
+ buf.release()
isTrue = (val > 0) == (iast.op == "ifdef")
if LogFlag {
logf("%s lhs=%q value=%q => %t", iast.op, iast.lhs, value, isTrue)
@@ -513,14 +513,14 @@ func (ev *Evaluator) evalIf(iast *ifAST) error {
case "ifeq", "ifneq":
lexpr := iast.lhs
rexpr := iast.rhs
- buf := newBuf()
+ buf := newEbuf()
params, err := ev.args(buf, lexpr, rexpr)
if err != nil {
return iast.errorf("%v\n (%s,%s)", err, lexpr, rexpr)
}
lhs := string(params[0])
rhs := string(params[1])
- freeBuf(buf)
+ buf.release()
isTrue = (lhs == rhs) == (iast.op == "ifeq")
if LogFlag {
logf("%s lhs=%q %q rhs=%q %q => %t", iast.op, iast.lhs, lhs, iast.rhs, rhs, isTrue)
@@ -552,8 +552,8 @@ func (ev *Evaluator) evalExport(ast *exportAST) error {
if err != nil {
return ast.errorf("failed to parse: %q: %v", string(ast.expr), err)
}
- var buf buffer
- buf.resetSpace()
+ var buf evalBuffer
+ buf.resetSep()
err = v.Eval(&buf, ev)
if err != nil {
return ast.errorf("%v\n expr:%s", err, v)
diff --git a/evalcmd.go b/evalcmd.go
index 7d15981..14c06e5 100644
--- a/evalcmd.go
+++ b/evalcmd.go
@@ -239,13 +239,13 @@ func (r runner) eval(ev *Evaluator, s string) ([]runner, error) {
if err != nil {
return nil, ev.errorf("parse cmd %q: %v", r.cmd, err)
}
- buf := newBuf()
+ buf := newEbuf()
err = expr.Eval(buf, ev)
if err != nil {
return nil, err
}
cmds := buf.String()
- freeBuf(buf)
+ buf.release()
logf("evalcmd: %q => %q", r.cmd, cmds)
var runners []runner
for _, cmd := range strings.Split(cmds, "\n") {
diff --git a/expr.go b/expr.go
index f9ce520..b7ee6c4 100644
--- a/expr.go
+++ b/expr.go
@@ -35,7 +35,7 @@ type evalWriter interface {
io.Writer
writeWord([]byte)
writeWordString(string)
- resetSpace()
+ resetSep()
}
// Value is an interface for value.
@@ -92,7 +92,7 @@ func (e expr) String() string {
func (e expr) Eval(w evalWriter, ev *Evaluator) error {
for _, v := range e {
- w.resetSpace()
+ w.resetSep()
err := v.Eval(w, ev)
if err != nil {
return err
@@ -153,13 +153,13 @@ func (v *varref) String() string {
func (v *varref) Eval(w evalWriter, ev *Evaluator) error {
te := traceEvent.begin("var", v, traceEventMain)
- buf := newBuf()
+ buf := newEbuf()
err := v.varname.Eval(buf, ev)
if err != nil {
return err
}
vv := ev.LookupVar(buf.String())
- freeBuf(buf)
+ buf.release()
err = vv.Eval(w, ev)
if err != nil {
return err
@@ -234,7 +234,7 @@ func (v varsubst) String() string {
func (v varsubst) Eval(w evalWriter, ev *Evaluator) error {
te := traceEvent.begin("varsubst", v, traceEventMain)
- buf := newBuf()
+ buf := newEbuf()
params, err := ev.args(buf, v.varname, v.pat, v.subst)
if err != nil {
return err
@@ -249,7 +249,7 @@ func (v varsubst) Eval(w evalWriter, ev *Evaluator) error {
return err
}
vals := splitSpaces(buf.String())
- freeBuf(buf)
+ buf.release()
space := false
for _, val := range vals {
if space {
diff --git a/fileutil.go b/fileutil.go
index 610fd73..fd721ef 100644
--- a/fileutil.go
+++ b/fileutil.go
@@ -38,8 +38,8 @@ func existsInVPATH(ev *Evaluator, target string) (string, bool) {
}
// TODO(ukai): support vpath directive (pattern vpath).
// TODO(ukai): ok to cache vpath value?
- var wb wordBuffer
- err := vpath.Eval(&wb, ev)
+ wb := newWbuf()
+ err := vpath.Eval(wb, ev)
if err != nil {
return target, false
}
@@ -53,5 +53,6 @@ func existsInVPATH(ev *Evaluator, target string) (string, bool) {
}
}
}
+ wb.release()
return target, false
}
diff --git a/func.go b/func.go
index 8f17517..5336914 100644
--- a/func.go
+++ b/func.go
@@ -172,7 +172,7 @@ func (f *funcSubst) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- abuf := newBuf()
+ abuf := newEbuf()
fargs, err := ev.args(abuf, f.args[1:]...)
if err != nil {
return err
@@ -188,7 +188,7 @@ func (f *funcSubst) Eval(w evalWriter, ev *Evaluator) error {
} else {
w.Write(bytes.Replace(text, from, to, -1))
}
- freeBuf(abuf)
+ abuf.release()
stats.add("funcbody", "subst", t)
return nil
}
@@ -201,13 +201,13 @@ func (f *funcPatsubst) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- abuf := newBuf()
+ abuf := newEbuf()
fargs, err := ev.args(abuf, f.args[1], f.args[2])
if err != nil {
return err
}
- var wb wordBuffer
- err = f.args[3].Eval(&wb, ev)
+ wb := newWbuf()
+ err = f.args[3].Eval(wb, ev)
if err != nil {
return err
}
@@ -224,7 +224,8 @@ func (f *funcPatsubst) Eval(w evalWriter, ev *Evaluator) error {
}
w.writeWord(sword)
}
- freeBuf(abuf)
+ abuf.release()
+ wb.release()
stats.add("funcbody", "patsubst", t)
return nil
}
@@ -237,8 +238,8 @@ func (f *funcStrip) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- var wb wordBuffer
- err = f.args[1].Eval(&wb, ev)
+ wb := newWbuf()
+ err = f.args[1].Eval(wb, ev)
if err != nil {
return err
}
@@ -246,6 +247,7 @@ func (f *funcStrip) Eval(w evalWriter, ev *Evaluator) error {
for _, word := range wb.words {
w.writeWord(word)
}
+ wb.release()
stats.add("funcbody", "strip", t)
return nil
}
@@ -258,7 +260,7 @@ func (f *funcFindstring) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- abuf := newBuf()
+ abuf := newEbuf()
fargs, err := ev.args(abuf, f.args[1:]...)
if err != nil {
return err
@@ -269,7 +271,7 @@ func (f *funcFindstring) Eval(w evalWriter, ev *Evaluator) error {
if bytes.Index(text, find) >= 0 {
w.Write(find)
}
- freeBuf(abuf)
+ abuf.release()
stats.add("funcbody", "findstring", t)
return nil
}
@@ -282,13 +284,13 @@ func (f *funcFilter) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- var patternsBuffer wordBuffer
- err = f.args[1].Eval(&patternsBuffer, ev)
+ patternsBuffer := newWbuf()
+ err = f.args[1].Eval(patternsBuffer, ev)
if err != nil {
return err
}
- var textBuffer wordBuffer
- err = f.args[2].Eval(&textBuffer, ev)
+ textBuffer := newWbuf()
+ err = f.args[2].Eval(textBuffer, ev)
if err != nil {
return err
}
@@ -300,6 +302,8 @@ func (f *funcFilter) Eval(w evalWriter, ev *Evaluator) error {
}
}
}
+ patternsBuffer.release()
+ textBuffer.release()
stats.add("funcbody", "filter", t)
return nil
}
@@ -312,13 +316,13 @@ func (f *funcFilterOut) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- var patternsBuffer wordBuffer
- err = f.args[1].Eval(&patternsBuffer, ev)
+ patternsBuffer := newWbuf()
+ err = f.args[1].Eval(patternsBuffer, ev)
if err != nil {
return err
}
- var textBuffer wordBuffer
- err = f.args[2].Eval(&textBuffer, ev)
+ textBuffer := newWbuf()
+ err = f.args[2].Eval(textBuffer, ev)
if err != nil {
return err
}
@@ -332,6 +336,8 @@ Loop:
}
w.writeWord(text)
}
+ patternsBuffer.release()
+ textBuffer.release()
stats.add("funcbody", "filter-out", t)
return err
}
@@ -344,8 +350,8 @@ func (f *funcSort) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- var wb wordBuffer
- err = f.args[1].Eval(&wb, ev)
+ wb := newWbuf()
+ err = f.args[1].Eval(wb, ev)
if err != nil {
return err
}
@@ -354,6 +360,7 @@ func (f *funcSort) Eval(w evalWriter, ev *Evaluator) error {
for _, tok := range wb.words {
toks = append(toks, string(tok))
}
+ wb.release()
sort.Strings(toks)
// Remove duplicate words.
@@ -377,13 +384,13 @@ func (f *funcWord) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- abuf := newBuf()
+ abuf := newEbuf()
err = f.args[1].Eval(abuf, ev)
if err != nil {
return err
}
v := string(trimSpaceBytes(abuf.Bytes()))
- freeBuf(abuf)
+ abuf.release()
index, ok := numericValueForFunc(v)
if !ok {
return ev.errorf(`*** non-numeric first argument to "word" function: %q.`, v)
@@ -391,8 +398,8 @@ func (f *funcWord) Eval(w evalWriter, ev *Evaluator) error {
if index == 0 {
return ev.errorf(`*** first argument to "word" function must be greater than 0.`)
}
- var wb wordBuffer
- err = f.args[2].Eval(&wb, ev)
+ wb := newWbuf()
+ err = f.args[2].Eval(wb, ev)
if err != nil {
return err
}
@@ -400,6 +407,7 @@ func (f *funcWord) Eval(w evalWriter, ev *Evaluator) error {
if index-1 < len(wb.words) {
w.writeWord(wb.words[index-1])
}
+ wb.release()
stats.add("funcbody", "word", t)
return err
}
@@ -412,7 +420,7 @@ func (f *funcWordlist) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- abuf := newBuf()
+ abuf := newEbuf()
fargs, err := ev.args(abuf, f.args[1], f.args[2])
if err != nil {
return err
@@ -431,10 +439,10 @@ func (f *funcWordlist) Eval(w evalWriter, ev *Evaluator) error {
if !ok {
return ev.errorf(`*** non-numeric second argument to "wordlist" function: %q.`, v)
}
- freeBuf(abuf)
+ abuf.release()
- var wb wordBuffer
- err = f.args[3].Eval(&wb, ev)
+ wb := newWbuf()
+ err = f.args[3].Eval(wb, ev)
if err != nil {
return err
}
@@ -443,6 +451,7 @@ func (f *funcWordlist) Eval(w evalWriter, ev *Evaluator) error {
w.writeWord(word)
}
}
+ wb.release()
stats.add("funcbody", "wordlist", t)
return nil
}
@@ -455,13 +464,14 @@ func (f *funcWords) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- var wb wordBuffer
- err = f.args[1].Eval(&wb, ev)
+ wb := newWbuf()
+ err = f.args[1].Eval(wb, ev)
if err != nil {
return err
}
t := time.Now()
n := len(wb.words)
+ wb.release()
w.writeWordString(strconv.Itoa(n))
stats.add("funcbody", "words", t)
return nil
@@ -475,8 +485,8 @@ func (f *funcFirstword) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- var wb wordBuffer
- err = f.args[1].Eval(&wb, ev)
+ wb := newWbuf()
+ err = f.args[1].Eval(wb, ev)
if err != nil {
return err
}
@@ -484,6 +494,7 @@ func (f *funcFirstword) Eval(w evalWriter, ev *Evaluator) error {
if len(wb.words) > 0 {
w.writeWord(wb.words[0])
}
+ wb.release()
stats.add("funcbody", "firstword", t)
return nil
}
@@ -496,8 +507,8 @@ func (f *funcLastword) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- var wb wordBuffer
- err = f.args[1].Eval(&wb, ev)
+ wb := newWbuf()
+ err = f.args[1].Eval(wb, ev)
if err != nil {
return err
}
@@ -505,6 +516,7 @@ func (f *funcLastword) Eval(w evalWriter, ev *Evaluator) error {
if len(wb.words) > 0 {
w.writeWord(wb.words[len(wb.words)-1])
}
+ wb.release()
stats.add("funcbody", "lastword", t)
return err
}
@@ -519,13 +531,13 @@ func (f *funcJoin) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- var wb1 wordBuffer
- err = f.args[1].Eval(&wb1, ev)
+ wb1 := newWbuf()
+ err = f.args[1].Eval(wb1, ev)
if err != nil {
return err
}
- var wb2 wordBuffer
- err = f.args[2].Eval(&wb2, ev)
+ wb2 := newWbuf()
+ err = f.args[2].Eval(wb2, ev)
if err != nil {
return err
}
@@ -540,6 +552,8 @@ func (f *funcJoin) Eval(w evalWriter, ev *Evaluator) error {
}
w.writeWord(word)
}
+ wb1.release()
+ wb2.release()
stats.add("funcbody", "join", t)
return nil
}
@@ -552,8 +566,8 @@ func (f *funcWildcard) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- var wb wordBuffer
- err = f.args[1].Eval(&wb, ev)
+ wb := newWbuf()
+ err = f.args[1].Eval(wb, ev)
if err != nil {
return err
}
@@ -563,6 +577,7 @@ func (f *funcWildcard) Eval(w evalWriter, ev *Evaluator) error {
io.WriteString(w, "$(/bin/ls -d ")
w.Write(wb.Bytes())
io.WriteString(w, " 2> /dev/null)")
+ wb.release()
traceEvent.end(te)
return nil
}
@@ -574,6 +589,7 @@ func (f *funcWildcard) Eval(w evalWriter, ev *Evaluator) error {
return err
}
}
+ wb.release()
traceEvent.end(te)
stats.add("funcbody", "wildcard", t)
return nil
@@ -587,8 +603,8 @@ func (f *funcDir) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- var wb wordBuffer
- err = f.args[1].Eval(&wb, ev)
+ wb := newWbuf()
+ err = f.args[1].Eval(wb, ev)
if err != nil {
return err
}
@@ -601,6 +617,7 @@ func (f *funcDir) Eval(w evalWriter, ev *Evaluator) error {
}
w.writeWordString(name + string(filepath.Separator))
}
+ wb.release()
stats.add("funcbody", "dir", t)
return nil
}
@@ -613,8 +630,8 @@ func (f *funcNotdir) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- var wb wordBuffer
- err = f.args[1].Eval(&wb, ev)
+ wb := newWbuf()
+ err = f.args[1].Eval(wb, ev)
if err != nil {
return err
}
@@ -627,6 +644,7 @@ func (f *funcNotdir) Eval(w evalWriter, ev *Evaluator) error {
}
w.writeWordString(filepath.Base(name))
}
+ wb.release()
stats.add("funcbody", "notdir", t)
return nil
}
@@ -639,8 +657,8 @@ func (f *funcSuffix) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- var wb wordBuffer
- err = f.args[1].Eval(&wb, ev)
+ wb := newWbuf()
+ err = f.args[1].Eval(wb, ev)
if err != nil {
return err
}
@@ -652,6 +670,7 @@ func (f *funcSuffix) Eval(w evalWriter, ev *Evaluator) error {
w.writeWordString(e)
}
}
+ wb.release()
stats.add("funcbody", "suffix", t)
return err
}
@@ -664,8 +683,8 @@ func (f *funcBasename) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- var wb wordBuffer
- err = f.args[1].Eval(&wb, ev)
+ wb := newWbuf()
+ err = f.args[1].Eval(wb, ev)
if err != nil {
return err
}
@@ -675,6 +694,7 @@ func (f *funcBasename) Eval(w evalWriter, ev *Evaluator) error {
e := stripExt(tok)
w.writeWordString(e)
}
+ wb.release()
stats.add("funcbody", "basename", t)
return nil
}
@@ -687,13 +707,13 @@ func (f *funcAddsuffix) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- abuf := newBuf()
+ abuf := newEbuf()
err = f.args[1].Eval(abuf, ev)
if err != nil {
return err
}
- var wb wordBuffer
- err = f.args[2].Eval(&wb, ev)
+ wb := newWbuf()
+ err = f.args[2].Eval(wb, ev)
if err != nil {
return err
}
@@ -705,7 +725,8 @@ func (f *funcAddsuffix) Eval(w evalWriter, ev *Evaluator) error {
name = append(name, suf...)
w.writeWord(name)
}
- freeBuf(abuf)
+ wb.release()
+ abuf.release()
stats.add("funcbody", "addsuffix", t)
return err
}
@@ -718,14 +739,14 @@ func (f *funcAddprefix) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- abuf := newBuf()
+ abuf := newEbuf()
err = f.args[1].Eval(abuf, ev)
if err != nil {
return err
}
pre := abuf.Bytes()
- var wb wordBuffer
- err = f.args[2].Eval(&wb, ev)
+ wb := newWbuf()
+ err = f.args[2].Eval(wb, ev)
if err != nil {
return err
}
@@ -736,7 +757,8 @@ func (f *funcAddprefix) Eval(w evalWriter, ev *Evaluator) error {
name = append(name, word...)
w.writeWord(name)
}
- freeBuf(abuf)
+ wb.release()
+ abuf.release()
stats.add("funcbody", "addprefix", t)
return err
}
@@ -754,8 +776,8 @@ func (f *funcRealpath) Eval(w evalWriter, ev *Evaluator) error {
ev.hasIO = true
return nil
}
- var wb wordBuffer
- err = f.args[1].Eval(&wb, ev)
+ wb := newWbuf()
+ err = f.args[1].Eval(wb, ev)
if err != nil {
return err
}
@@ -774,6 +796,7 @@ func (f *funcRealpath) Eval(w evalWriter, ev *Evaluator) error {
}
w.writeWordString(name)
}
+ wb.release()
stats.add("funcbody", "realpath", t)
return err
}
@@ -786,8 +809,8 @@ func (f *funcAbspath) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- var wb wordBuffer
- err = f.args[1].Eval(&wb, ev)
+ wb := newWbuf()
+ err = f.args[1].Eval(wb, ev)
if err != nil {
return err
}
@@ -801,6 +824,7 @@ func (f *funcAbspath) Eval(w evalWriter, ev *Evaluator) error {
}
w.writeWordString(name)
}
+ wb.release()
stats.add("funcbody", "abspath", t)
return nil
}
@@ -814,16 +838,16 @@ func (f *funcIf) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- abuf := newBuf()
+ abuf := newEbuf()
err = f.args[1].Eval(abuf, ev)
if err != nil {
return err
}
if len(abuf.Bytes()) != 0 {
- freeBuf(abuf)
+ abuf.release()
return f.args[2].Eval(w, ev)
}
- freeBuf(abuf)
+ abuf.release()
if len(f.args) > 3 {
return f.args[3].Eval(w, ev)
}
@@ -838,7 +862,7 @@ func (f *funcAnd) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return nil
}
- abuf := newBuf()
+ abuf := newEbuf()
var cond []byte
for _, arg := range f.args[1:] {
abuf.Reset()
@@ -848,12 +872,12 @@ func (f *funcAnd) Eval(w evalWriter, ev *Evaluator) error {
}
cond = abuf.Bytes()
if len(cond) == 0 {
- freeBuf(abuf)
+ abuf.release()
return nil
}
}
w.Write(cond)
- freeBuf(abuf)
+ abuf.release()
return nil
}
@@ -865,7 +889,7 @@ func (f *funcOr) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- abuf := newBuf()
+ abuf := newEbuf()
for _, arg := range f.args[1:] {
abuf.Reset()
err = arg.Eval(abuf, ev)
@@ -875,11 +899,11 @@ func (f *funcOr) Eval(w evalWriter, ev *Evaluator) error {
cond := abuf.Bytes()
if len(cond) != 0 {
w.Write(cond)
- freeBuf(abuf)
+ abuf.release()
return nil
}
}
- freeBuf(abuf)
+ abuf.release()
return nil
}
@@ -910,7 +934,7 @@ func (f *funcShell) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- abuf := newBuf()
+ abuf := newEbuf()
err = f.args[1].Eval(abuf, ev)
if err != nil {
return err
@@ -922,11 +946,11 @@ func (f *funcShell) Eval(w evalWriter, ev *Evaluator) error {
w.Write(abuf.Bytes())
writeByte(w, ')')
traceEvent.end(te)
- freeBuf(abuf)
+ abuf.release()
return nil
}
arg := abuf.String()
- freeBuf(abuf)
+ abuf.release()
shellVar, err := ev.EvaluateVar("SHELL")
if err != nil {
return err
@@ -985,7 +1009,7 @@ type funcCall struct{ fclosure }
func (f *funcCall) Arity() int { return 0 }
func (f *funcCall) Eval(w evalWriter, ev *Evaluator) error {
- abuf := newBuf()
+ abuf := newEbuf()
fargs, err := ev.args(abuf, f.args[1:]...)
if err != nil {
return err
@@ -1028,7 +1052,7 @@ func (f *funcCall) Eval(w evalWriter, ev *Evaluator) error {
if LogFlag {
logf("call %q variable %q return %q", f.args[1], variable, buf.Bytes())
}
- freeBuf(abuf)
+ abuf.release()
return nil
}
@@ -1041,13 +1065,13 @@ func (f *funcValue) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- abuf := newBuf()
+ abuf := newEbuf()
err = f.args[1].Eval(abuf, ev)
if err != nil {
return err
}
v := ev.LookupVar(abuf.String())
- freeBuf(abuf)
+ abuf.release()
io.WriteString(w, v.String())
return nil
}
@@ -1061,7 +1085,7 @@ func (f *funcEval) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- abuf := newBuf()
+ abuf := newEbuf()
err = f.args[1].Eval(abuf, ev)
if err != nil {
return err
@@ -1079,7 +1103,7 @@ func (f *funcEval) Eval(w evalWriter, ev *Evaluator) error {
return err
}
}
- freeBuf(abuf)
+ abuf.release()
return nil
}
@@ -1194,8 +1218,8 @@ func (f *funcEvalAssign) String() string {
}
func (f *funcEvalAssign) Eval(w evalWriter, ev *Evaluator) error {
- var abuf buffer
- abuf.resetSpace()
+ var abuf evalBuffer
+ abuf.resetSep()
err := f.rhs.Eval(&abuf, ev)
if err != nil {
return err
@@ -1211,13 +1235,13 @@ func (f *funcEvalAssign) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return ev.errorf("eval assign error: %q: %v", f.String(), err)
}
- vbuf := newBuf()
+ vbuf := newEbuf()
err = exp.Eval(vbuf, ev)
if err != nil {
return err
}
rvalue = &simpleVar{value: vbuf.String(), origin: "file"}
- freeBuf(vbuf)
+ vbuf.release()
case "=":
rvalue = &recursiveVar{expr: tmpval(rhs), origin: "file"}
case "+=":
@@ -1271,13 +1295,13 @@ func (f *funcOrigin) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- abuf := newBuf()
+ abuf := newEbuf()
err = f.args[1].Eval(abuf, ev)
if err != nil {
return err
}
v := ev.LookupVar(abuf.String())
- freeBuf(abuf)
+ abuf.release()
io.WriteString(w, v.Origin())
return nil
}
@@ -1291,13 +1315,13 @@ func (f *funcFlavor) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- abuf := newBuf()
+ abuf := newEbuf()
err = f.args[1].Eval(abuf, ev)
if err != nil {
return err
}
v := ev.LookupVar(abuf.String())
- freeBuf(abuf)
+ abuf.release()
io.WriteString(w, v.Flavor())
return nil
}
@@ -1316,13 +1340,13 @@ func (f *funcInfo) Eval(w evalWriter, ev *Evaluator) error {
ev.hasIO = true
return nil
}
- abuf := newBuf()
+ abuf := newEbuf()
err = f.args[1].Eval(abuf, ev)
if err != nil {
return err
}
fmt.Printf("%s\n", abuf.String())
- freeBuf(abuf)
+ abuf.release()
return nil
}
@@ -1339,13 +1363,13 @@ func (f *funcWarning) Eval(w evalWriter, ev *Evaluator) error {
ev.hasIO = true
return nil
}
- abuf := newBuf()
+ abuf := newEbuf()
err = f.args[1].Eval(abuf, ev)
if err != nil {
return err
}
fmt.Printf("%s: %s\n", ev.srcpos, abuf.String())
- freeBuf(abuf)
+ abuf.release()
return nil
}
@@ -1362,8 +1386,8 @@ func (f *funcError) Eval(w evalWriter, ev *Evaluator) error {
ev.hasIO = true
return nil
}
- var abuf buffer
- abuf.resetSpace()
+ var abuf evalBuffer
+ abuf.resetSep()
err = f.args[1].Eval(&abuf, ev)
if err != nil {
return err
@@ -1381,15 +1405,15 @@ func (f *funcForeach) Eval(w evalWriter, ev *Evaluator) error {
if err != nil {
return err
}
- abuf := newBuf()
+ abuf := newEbuf()
err = f.args[1].Eval(abuf, ev)
if err != nil {
return err
}
varname := string(abuf.Bytes())
- freeBuf(abuf)
- var wb wordBuffer
- err = f.args[2].Eval(&wb, ev)
+ abuf.release()
+ wb := newWbuf()
+ err = f.args[2].Eval(wb, ev)
if err != nil {
return err
}
@@ -1407,6 +1431,7 @@ func (f *funcForeach) Eval(w evalWriter, ev *Evaluator) error {
}
space = true
}
+ wb.release()
av := ev.LookupVar(varname)
if _, ok := av.(*automaticVar); ok {
ev.outVars.Assign(varname, ov)
diff --git a/func_test.go b/func_test.go
index 8f3b81a..b56291e 100644
--- a/func_test.go
+++ b/func_test.go
@@ -26,7 +26,7 @@ func BenchmarkFuncStrip(b *testing.B) {
},
}
ev := NewEvaluator(make(map[string]Var))
- var buf buffer
+ var buf evalBuffer
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
@@ -45,7 +45,7 @@ func BenchmarkFuncSort(b *testing.B) {
},
}
ev := NewEvaluator(make(map[string]Var))
- var buf buffer
+ var buf evalBuffer
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
@@ -66,7 +66,7 @@ func BenchmarkFuncPatsubst(b *testing.B) {
},
}
ev := NewEvaluator(make(map[string]Var))
- var buf buffer
+ var buf evalBuffer
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
diff --git a/ioutil.go b/ioutil.go
deleted file mode 100644
index 8f89f6f..0000000
--- a/ioutil.go
+++ /dev/null
@@ -1,147 +0,0 @@
-// 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"
- "io"
- "sync"
-)
-
-var bufFree = sync.Pool{
- New: func() interface{} { return new(buffer) },
-}
-
-func writeByte(w io.Writer, b byte) error {
- if bw, ok := w.(io.ByteWriter); ok {
- return bw.WriteByte(b)
- }
- _, err := w.Write([]byte{b})
- return err
-}
-
-// use io.WriteString to stringWrite.
-
-type ssvWriter struct {
- io.Writer
- space bool
-}
-
-func (w *ssvWriter) writeWord(word []byte) {
- if w.space {
- writeByte(w.Writer, ' ')
- }
- w.space = true
- w.Writer.Write(word)
-}
-
-func (w *ssvWriter) writeWordString(word string) {
- if w.space {
- writeByte(w.Writer, ' ')
- }
- w.space = true
- io.WriteString(w.Writer, word)
-}
-
-func (w *ssvWriter) resetSpace() {
- w.space = false
-}
-
-type buffer struct {
- bytes.Buffer
- ssvWriter
- args [][]byte
-}
-
-func newBuf() *buffer {
- buf := bufFree.Get().(*buffer)
- buf.Reset()
- return buf
-}
-
-func freeBuf(buf *buffer) {
- if cap(buf.Bytes()) > 1024 {
- return
- }
- buf.Reset()
- buf.args = buf.args[:0]
- bufFree.Put(buf)
-}
-
-func (b *buffer) Reset() {
- b.Buffer.Reset()
- b.resetSpace()
-}
-
-func (b *buffer) resetSpace() {
- if b.ssvWriter.Writer == nil {
- b.ssvWriter.Writer = &b.Buffer
- }
- b.ssvWriter.resetSpace()
-}
-
-type wordBuffer struct {
- words [][]byte
- cont bool
-}
-
-func (wb *wordBuffer) Write(data []byte) (int, error) {
- if len(data) == 0 {
- return 0, nil
- }
- if isWhitespace(rune(data[0])) {
- wb.cont = false
- }
- ws := newWordScanner(data)
- for ws.Scan() {
- if wb.cont {
- word := wb.words[len(wb.words)-1]
- word = append(word, ws.Bytes()...)
- wb.words[len(wb.words)-1] = word
- wb.cont = false
- continue
- }
- wb.writeWord(ws.Bytes())
- }
- if !isWhitespace(rune(data[len(data)-1])) {
- wb.cont = true
- }
- return len(data), nil
-}
-
-func (wb *wordBuffer) writeWord(word []byte) {
- var w []byte
- w = append(w, word...)
- wb.words = append(wb.words, w)
-}
-
-func (wb *wordBuffer) writeWordString(word string) {
- wb.writeWord([]byte(word))
-}
-
-func (wb *wordBuffer) resetSpace() {}
-
-func (wb *wordBuffer) Bytes() []byte {
- var sp bool
- var b []byte
- for _, word := range wb.words {
- if sp {
- b = append(b, ' ')
- }
- b = append(b, word...)
- sp = true
- }
- return b
-}
diff --git a/shellutil.go b/shellutil.go
index aed1dfe..2275a93 100644
--- a/shellutil.go
+++ b/shellutil.go
@@ -256,14 +256,14 @@ func rot13(buf []byte) {
}
func (f *funcShellAndroidRot13) Eval(w evalWriter, ev *Evaluator) error {
- abuf := newBuf()
+ abuf := newEbuf()
fargs, err := ev.args(abuf, f.v)
if err != nil {
return err
}
rot13(fargs[0])
w.Write(fargs[0])
- freeBuf(abuf)
+ abuf.release()
return nil
}
@@ -273,13 +273,13 @@ type funcShellAndroidFindFileInDir struct {
}
func (f *funcShellAndroidFindFileInDir) Eval(w evalWriter, ev *Evaluator) error {
- abuf := newBuf()
+ abuf := newEbuf()
fargs, err := ev.args(abuf, f.dir)
if err != nil {
return err
}
dir := string(trimSpaceBytes(fargs[0]))
- freeBuf(abuf)
+ abuf.release()
logf("shellAndroidFindFileInDir %s => %s", f.dir.String(), dir)
if strings.Contains(dir, "..") {
logf("shellAndroidFindFileInDir contains ..: call original shell")
@@ -301,15 +301,15 @@ type funcShellAndroidFindExtFilesUnder struct {
}
func (f *funcShellAndroidFindExtFilesUnder) Eval(w evalWriter, ev *Evaluator) error {
- abuf := newBuf()
+ abuf := newEbuf()
err := f.chdir.Eval(abuf, ev)
if err != nil {
return err
}
chdir := string(trimSpaceBytes(abuf.Bytes()))
- freeBuf(abuf)
- var wb wordBuffer
- err = f.roots.Eval(&wb, ev)
+ abuf.release()
+ wb := newWbuf()
+ err = f.roots.Eval(wb, ev)
if err != nil {
return err
}
@@ -322,6 +322,7 @@ func (f *funcShellAndroidFindExtFilesUnder) Eval(w evalWriter, ev *Evaluator) er
}
roots = append(roots, root)
}
+ wb.release()
logf("shellAndroidFindExtFilesUnder %s,%s => %s,%s", f.chdir.String(), f.roots.String(), chdir, roots)
if strings.Contains(chdir, "..") || hasDotDot {
logf("shellAndroidFindExtFilesUnder contains ..: call original shell")
@@ -331,16 +332,16 @@ func (f *funcShellAndroidFindExtFilesUnder) Eval(w evalWriter, ev *Evaluator) er
logf("shellAndroidFindExtFilesUnder androidFindCache is not ready: call original shell")
return f.funcShell.Eval(w, ev)
}
- buf := newBuf()
+ buf := newEbuf()
for _, root := range roots {
if !androidFindCache.findExtFilesUnder(buf, chdir, root, f.ext) {
- freeBuf(buf)
+ buf.release()
logf("shellAndroidFindExtFilesUnder androidFindCache couldn't handle: call original shell")
return f.funcShell.Eval(w, ev)
}
}
w.Write(buf.Bytes())
- freeBuf(buf)
+ buf.release()
return nil
}
@@ -350,13 +351,13 @@ type funcShellAndroidFindJavaResourceFileGroup struct {
}
func (f *funcShellAndroidFindJavaResourceFileGroup) Eval(w evalWriter, ev *Evaluator) error {
- abuf := newBuf()
+ abuf := newEbuf()
fargs, err := ev.args(abuf, f.dir)
if err != nil {
return err
}
dir := string(trimSpaceBytes(fargs[0]))
- freeBuf(abuf)
+ abuf.release()
logf("shellAndroidFindJavaResourceFileGroup %s => %s", f.dir.String(), dir)
if strings.Contains(dir, "..") {
logf("shellAndroidFindJavaResourceFileGroup contains ..: call original shell")
@@ -383,7 +384,7 @@ func (f *funcShellAndroidFindleaves) Eval(w evalWriter, ev *Evaluator) error {
logf("shellAndroidFindleaves androidFindCache is not ready: call original shell")
return f.funcShell.Eval(w, ev)
}
- abuf := newBuf()
+ abuf := newEbuf()
var params []Value
params = append(params, f.name)
params = append(params, f.prunes...)
@@ -396,10 +397,10 @@ func (f *funcShellAndroidFindleaves) Eval(w evalWriter, ev *Evaluator) error {
for _, arg := range fargs[1:] {
prunes = append(prunes, string(trimSpaceBytes(arg)))
}
- freeBuf(abuf)
+ abuf.release()
- var wb wordBuffer
- err = f.dirlist.Eval(&wb, ev)
+ wb := newWbuf()
+ err = f.dirlist.Eval(wb, ev)
if err != nil {
return err
}
@@ -412,6 +413,7 @@ func (f *funcShellAndroidFindleaves) Eval(w evalWriter, ev *Evaluator) error {
}
dirs = append(dirs, dir)
}
+ wb.release()
for _, dir := range dirs {
androidFindCache.findleaves(w, dir, name, prunes, f.mindepth)
diff --git a/var.go b/var.go
index 87f032e..c995265 100644
--- a/var.go
+++ b/var.go
@@ -119,7 +119,7 @@ func (v *simpleVar) Append(ev *Evaluator, s string) (Var, error) {
if err != nil {
return nil, err
}
- abuf := newBuf()
+ abuf := newEbuf()
io.WriteString(abuf, v.value)
writeByte(abuf, ' ')
err = val.Eval(abuf, ev)
@@ -127,12 +127,12 @@ func (v *simpleVar) Append(ev *Evaluator, s string) (Var, error) {
return nil, err
}
v.value = abuf.String()
- freeBuf(abuf)
+ abuf.release()
return v, nil
}
func (v *simpleVar) AppendVar(ev *Evaluator, val Value) (Var, error) {
- abuf := newBuf()
+ abuf := newEbuf()
io.WriteString(abuf, v.value)
writeByte(abuf, ' ')
err := val.Eval(abuf, ev)
@@ -140,7 +140,7 @@ func (v *simpleVar) AppendVar(ev *Evaluator, val Value) (Var, error) {
return nil, err
}
v.value = abuf.String()
- freeBuf(abuf)
+ abuf.release()
return v, nil
}
@@ -169,10 +169,10 @@ func (v *automaticVar) Append(ev *Evaluator, s string) (Var, error) {
if err != nil {
return nil, err
}
- var buf buffer
+ var buf evalBuffer
buf.Write(v.value)
buf.WriteByte(' ')
- buf.resetSpace()
+ buf.resetSep()
err = val.Eval(&buf, ev)
if err != nil {
return nil, err
@@ -184,10 +184,10 @@ func (v *automaticVar) Append(ev *Evaluator, s string) (Var, error) {
}
func (v *automaticVar) AppendVar(ev *Evaluator, val Value) (Var, error) {
- var buf buffer
+ var buf evalBuffer
buf.Write(v.value)
buf.WriteByte(' ')
- buf.resetSpace()
+ buf.resetSep()
err := val.Eval(&buf, ev)
if err != nil {
return nil, err