aboutsummaryrefslogtreecommitdiff
path: root/func.go
diff options
context:
space:
mode:
authorFumitoshi Ukai <fumitoshi.ukai@gmail.com>2015-05-07 12:56:12 +0900
committerFumitoshi Ukai <fumitoshi.ukai@gmail.com>2015-05-07 15:12:44 +0900
commitb06cd9d54075f942445f0030da9993368a1f49ab (patch)
tree6a99750aeed9863b8040c6f6d3d8d2402a4c74de /func.go
parent5ca0ecded9bc653fd9de59a2fad414d6f2da3bcf (diff)
downloadkati-b06cd9d54075f942445f0030da9993368a1f49ab.tar.gz
use sync.Pool for temporal bytes.Buffer.
remove ev.Value and ev.Values before: scanblock: 8.22s (14.83%) runtime.MScan_Sweep 4.99s(9.00%) after: scanblock: 7.42s (12.95%) runtime.MScan_Sweep 4.57s(7.98%)
Diffstat (limited to 'func.go')
-rw-r--r--func.go250
1 files changed, 183 insertions, 67 deletions
diff --git a/func.go b/func.go
index 0d6bb53..e2352c8 100644
--- a/func.go
+++ b/func.go
@@ -100,13 +100,12 @@ func (sw *ssvWriter) WriteString(s string) {
sw.Write([]byte(s))
}
-func numericValueForFunc(ev *Evaluator, v Value, funcName string, nth string) int {
- a := bytes.TrimSpace(ev.Value(v))
- n, err := strconv.Atoi(string(a))
+func numericValueForFunc(v string) (int, bool) {
+ n, err := strconv.Atoi(v)
if err != nil || n < 0 {
- Error(ev.filename, ev.lineno, `*** non-numeric %s argument to "%s" function: "%s".`, nth, funcName, a)
+ return n, false
}
- return n
+ return n, true
}
type fclosure struct {
@@ -137,7 +136,7 @@ func (c *fclosure) String() string {
return fmt.Sprintf("$%s %s%c", arg0, strings.Join(args, ","), cp)
}
-func (c *fclosure) Serialize() SerializableVar{
+func (c *fclosure) Serialize() SerializableVar {
r := SerializableVar{Type: "func"}
for _, a := range c.args {
r.Children = append(r.Children, a.Serialize())
@@ -151,11 +150,14 @@ type funcSubst struct{ fclosure }
func (f *funcSubst) Arity() int { return 3 }
func (f *funcSubst) Eval(w io.Writer, ev *Evaluator) {
assertArity("subst", 3, len(f.args))
- from := ev.Value(f.args[1])
- to := ev.Value(f.args[2])
- text := ev.Value(f.args[3])
+ abuf := newBuf()
+ fargs := ev.args(abuf, f.args[1:]...)
+ from := fargs[0]
+ to := fargs[1]
+ text := fargs[2]
Log("subst from:%q to:%q text:%q", from, to, text)
w.Write(bytes.Replace(text, from, to, -1))
+ freeBuf(abuf)
}
type funcPatsubst struct{ fclosure }
@@ -163,14 +165,17 @@ type funcPatsubst struct{ fclosure }
func (f *funcPatsubst) Arity() int { return 3 }
func (f *funcPatsubst) Eval(w io.Writer, ev *Evaluator) {
assertArity("patsubst", 3, len(f.args))
- pat := ev.Value(f.args[1])
- repl := ev.Value(f.args[2])
- texts := splitSpacesBytes(ev.Value(f.args[3]))
+ abuf := newBuf()
+ fargs := ev.args(abuf, f.args[1:]...)
+ pat := fargs[0]
+ repl := fargs[1]
+ texts := splitSpacesBytes(fargs[2])
sw := ssvWriter{w: w}
for _, text := range texts {
t := substPatternBytes(pat, repl, text)
sw.Write(t)
}
+ freeBuf(abuf)
}
type funcStrip struct{ fclosure }
@@ -178,8 +183,10 @@ type funcStrip struct{ fclosure }
func (f *funcStrip) Arity() int { return 1 }
func (f *funcStrip) Eval(w io.Writer, ev *Evaluator) {
assertArity("strip", 1, len(f.args))
- text := ev.Value(f.args[1])
- w.Write(bytes.TrimSpace(text))
+ abuf := newBuf()
+ f.args[1].Eval(abuf, ev)
+ w.Write(trimSpaceBytes(abuf.Bytes()))
+ freeBuf(abuf)
}
type funcFindstring struct{ fclosure }
@@ -187,11 +194,14 @@ type funcFindstring struct{ fclosure }
func (f *funcFindstring) Arity() int { return 2 }
func (f *funcFindstring) Eval(w io.Writer, ev *Evaluator) {
assertArity("findstring", 2, len(f.args))
- find := ev.Value(f.args[1])
- text := ev.Value(f.args[2])
+ abuf := newBuf()
+ fargs := ev.args(abuf, f.args[1:]...)
+ find := fargs[0]
+ text := fargs[1]
if bytes.Index(text, find) >= 0 {
w.Write(find)
}
+ freeBuf(abuf)
}
type funcFilter struct{ fclosure }
@@ -199,8 +209,10 @@ type funcFilter struct{ fclosure }
func (f *funcFilter) Arity() int { return 2 }
func (f *funcFilter) Eval(w io.Writer, ev *Evaluator) {
assertArity("filter", 2, len(f.args))
- patterns := splitSpacesBytes(ev.Value(f.args[1]))
- texts := splitSpacesBytes(ev.Value(f.args[2]))
+ abuf := newBuf()
+ fargs := ev.args(abuf, f.args[1:]...)
+ patterns := splitSpacesBytes(fargs[0])
+ texts := splitSpacesBytes(fargs[1])
sw := ssvWriter{w: w}
for _, text := range texts {
for _, pat := range patterns {
@@ -209,6 +221,7 @@ func (f *funcFilter) Eval(w io.Writer, ev *Evaluator) {
}
}
}
+ freeBuf(abuf)
}
type funcFilterOut struct{ fclosure }
@@ -216,8 +229,10 @@ type funcFilterOut struct{ fclosure }
func (f *funcFilterOut) Arity() int { return 2 }
func (f *funcFilterOut) Eval(w io.Writer, ev *Evaluator) {
assertArity("filter-out", 2, len(f.args))
- patterns := splitSpacesBytes(ev.Value(f.args[1]))
- texts := splitSpacesBytes(ev.Value(f.args[2]))
+ abuf := newBuf()
+ fargs := ev.args(abuf, f.args[1:]...)
+ patterns := splitSpacesBytes(fargs[0])
+ texts := splitSpacesBytes(fargs[1])
sw := ssvWriter{w: w}
Loop:
for _, text := range texts {
@@ -228,6 +243,7 @@ Loop:
}
sw.Write(text)
}
+ freeBuf(abuf)
}
type funcSort struct{ fclosure }
@@ -235,7 +251,10 @@ type funcSort struct{ fclosure }
func (f *funcSort) Arity() int { return 1 }
func (f *funcSort) Eval(w io.Writer, ev *Evaluator) {
assertArity("sort", 1, len(f.args))
- toks := splitSpaces(string(ev.Value(f.args[1])))
+ abuf := newBuf()
+ f.args[1].Eval(abuf, ev)
+ toks := splitSpaces(abuf.String())
+ freeBuf(abuf)
sort.Strings(toks)
// Remove duplicate words.
@@ -254,15 +273,23 @@ type funcWord struct{ fclosure }
func (f *funcWord) Arity() int { return 2 }
func (f *funcWord) Eval(w io.Writer, ev *Evaluator) {
assertArity("word", 2, len(f.args))
- index := numericValueForFunc(ev, f.args[1], "word", "first")
+ abuf := newBuf()
+ fargs := ev.args(abuf, f.args[1:]...)
+ v := string(trimSpaceBytes(fargs[0]))
+ index, ok := numericValueForFunc(v)
+ if !ok {
+ Error(ev.filename, ev.lineno, `*** non-numeric first argument to "word" function: %q.`, v)
+ }
if index == 0 {
Error(ev.filename, ev.lineno, `*** first argument to "word" function must be greater than 0.`)
}
- toks := splitSpacesBytes(ev.Value(f.args[2]))
+ toks := splitSpacesBytes(fargs[1])
if index-1 >= len(toks) {
+ freeBuf(abuf)
return
}
w.Write(toks[index-1])
+ freeBuf(abuf)
}
type funcWordlist struct{ fclosure }
@@ -270,17 +297,28 @@ type funcWordlist struct{ fclosure }
func (f *funcWordlist) Arity() int { return 3 }
func (f *funcWordlist) Eval(w io.Writer, ev *Evaluator) {
assertArity("wordlist", 3, len(f.args))
- si := numericValueForFunc(ev, f.args[1], "wordlist", "first")
+ abuf := newBuf()
+ fargs := ev.args(abuf, f.args[1:]...)
+ v := string(trimSpaceBytes(fargs[0]))
+ si, ok := numericValueForFunc(v)
+ if !ok {
+ Error(ev.filename, ev.lineno, `*** non-numeric first argument to "wordlist" function: %q.`, v)
+ }
if si == 0 {
Error(ev.filename, ev.lineno, `*** invalid first argument to "wordlist" function: %s`, f.args[1])
}
- ei := numericValueForFunc(ev, f.args[2], "wordlist", "second")
+ v = string(trimSpaceBytes(fargs[1]))
+ ei, ok := numericValueForFunc(v)
+ if !ok {
+ Error(ev.filename, ev.lineno, `*** non-numeric second argument to "wordlist" function: %q.`, v)
+ }
if ei == 0 {
Error(ev.filename, ev.lineno, `*** invalid second argument to "wordlist" function: %s`, f.args[2])
}
- toks := splitSpacesBytes(ev.Value(f.args[3]))
+ toks := splitSpacesBytes(fargs[2])
if si-1 >= len(toks) {
+ freeBuf(abuf)
return
}
if ei-1 >= len(toks) {
@@ -291,6 +329,7 @@ func (f *funcWordlist) Eval(w io.Writer, ev *Evaluator) {
for _, t := range toks[si-1 : ei] {
sw.Write(t)
}
+ freeBuf(abuf)
}
type funcWords struct{ fclosure }
@@ -298,8 +337,11 @@ type funcWords struct{ fclosure }
func (f *funcWords) Arity() int { return 1 }
func (f *funcWords) Eval(w io.Writer, ev *Evaluator) {
assertArity("words", 1, len(f.args))
- toks := splitSpacesBytes(ev.Value(f.args[1]))
+ abuf := newBuf()
+ f.args[1].Eval(abuf, ev)
+ toks := splitSpacesBytes(abuf.Bytes())
w.Write([]byte(strconv.Itoa(len(toks))))
+ freeBuf(abuf)
}
type funcFirstword struct{ fclosure }
@@ -307,11 +349,15 @@ type funcFirstword struct{ fclosure }
func (f *funcFirstword) Arity() int { return 1 }
func (f *funcFirstword) Eval(w io.Writer, ev *Evaluator) {
assertArity("firstword", 1, len(f.args))
- toks := splitSpacesBytes(ev.Value(f.args[1]))
+ abuf := newBuf()
+ f.args[1].Eval(abuf, ev)
+ toks := splitSpacesBytes(abuf.Bytes())
if len(toks) == 0 {
+ freeBuf(abuf)
return
}
w.Write(toks[0])
+ freeBuf(abuf)
}
type funcLastword struct{ fclosure }
@@ -319,11 +365,15 @@ type funcLastword struct{ fclosure }
func (f *funcLastword) Arity() int { return 1 }
func (f *funcLastword) Eval(w io.Writer, ev *Evaluator) {
assertArity("lastword", 1, len(f.args))
- toks := splitSpacesBytes(ev.Value(f.args[1]))
+ abuf := newBuf()
+ f.args[1].Eval(abuf, ev)
+ toks := splitSpacesBytes(abuf.Bytes())
if len(toks) == 0 {
+ freeBuf(abuf)
return
}
w.Write(toks[len(toks)-1])
+ freeBuf(abuf)
}
// https://www.gnu.org/software/make/manual/html_node/File-Name-Functions.html#File-Name-Functions
@@ -333,8 +383,10 @@ type funcJoin struct{ fclosure }
func (f *funcJoin) Arity() int { return 2 }
func (f *funcJoin) Eval(w io.Writer, ev *Evaluator) {
assertArity("join", 2, len(f.args))
- list1 := splitSpacesBytes(ev.Value(f.args[1]))
- list2 := splitSpacesBytes(ev.Value(f.args[2]))
+ abuf := newBuf()
+ fargs := ev.args(abuf, f.args[1:]...)
+ list1 := splitSpacesBytes(fargs[0])
+ list2 := splitSpacesBytes(fargs[1])
sw := ssvWriter{w: w}
for i, v := range list1 {
if i < len(list2) {
@@ -350,6 +402,7 @@ func (f *funcJoin) Eval(w io.Writer, ev *Evaluator) {
sw.Write(v)
}
}
+ freeBuf(abuf)
}
type funcWildcard struct{ fclosure }
@@ -361,8 +414,12 @@ func (f *funcWildcard) Eval(w io.Writer, ev *Evaluator) {
ev.hasIO = true
return
}
+ abuf := newBuf()
+ f.args[1].Eval(abuf, ev)
+ patterns := splitSpaces(abuf.String())
+ freeBuf(abuf)
sw := ssvWriter{w: w}
- for _, pattern := range splitSpaces(string(ev.Value(f.args[1]))) {
+ for _, pattern := range patterns {
files, err := filepath.Glob(pattern)
if err != nil {
panic(err)
@@ -382,7 +439,10 @@ func (f *funcDir) Eval(w io.Writer, ev *Evaluator) {
ev.hasIO = true
return
}
- names := splitSpaces(string(ev.Value(f.args[1])))
+ abuf := newBuf()
+ f.args[1].Eval(abuf, ev)
+ names := splitSpaces(abuf.String())
+ freeBuf(abuf)
sw := ssvWriter{w: w}
for _, name := range names {
if name == "/" {
@@ -402,7 +462,10 @@ func (f *funcNotdir) Eval(w io.Writer, ev *Evaluator) {
ev.hasIO = true
return
}
- names := splitSpaces(string(ev.Value(f.args[1])))
+ abuf := newBuf()
+ f.args[1].Eval(abuf, ev)
+ names := splitSpaces(abuf.String())
+ freeBuf(abuf)
sw := ssvWriter{w: w}
for _, name := range names {
if name == string(filepath.Separator) {
@@ -418,7 +481,10 @@ type funcSuffix struct{ fclosure }
func (f *funcSuffix) Arity() int { return 1 }
func (f *funcSuffix) Eval(w io.Writer, ev *Evaluator) {
assertArity("suffix", 1, len(f.args))
- toks := splitSpaces(string(ev.Value(f.args[1])))
+ abuf := newBuf()
+ f.args[1].Eval(abuf, ev)
+ toks := splitSpaces(abuf.String())
+ freeBuf(abuf)
sw := ssvWriter{w: w}
for _, tok := range toks {
e := filepath.Ext(tok)
@@ -433,7 +499,10 @@ type funcBasename struct{ fclosure }
func (f *funcBasename) Arity() int { return 1 }
func (f *funcBasename) Eval(w io.Writer, ev *Evaluator) {
assertArity("basename", 1, len(f.args))
- toks := splitSpaces(string(ev.Value(f.args[1])))
+ abuf := newBuf()
+ f.args[1].Eval(abuf, ev)
+ toks := splitSpaces(abuf.String())
+ freeBuf(abuf)
sw := ssvWriter{w: w}
for _, tok := range toks {
e := stripExt(tok)
@@ -446,14 +515,17 @@ type funcAddsuffix struct{ fclosure }
func (f *funcAddsuffix) Arity() int { return 2 }
func (f *funcAddsuffix) Eval(w io.Writer, ev *Evaluator) {
assertArity("addsuffix", 2, len(f.args))
- suf := ev.Value(f.args[1])
- toks := splitSpacesBytes(ev.Value(f.args[2]))
+ abuf := newBuf()
+ fargs := ev.args(abuf, f.args[1:]...)
+ suf := fargs[0]
+ toks := splitSpacesBytes(fargs[1])
sw := ssvWriter{w: w}
for _, tok := range toks {
sw.Write(tok)
// Use |w| not to append extra ' '.
w.Write(suf)
}
+ freeBuf(abuf)
}
type funcAddprefix struct{ fclosure }
@@ -461,14 +533,17 @@ type funcAddprefix struct{ fclosure }
func (f *funcAddprefix) Arity() int { return 2 }
func (f *funcAddprefix) Eval(w io.Writer, ev *Evaluator) {
assertArity("addprefix", 2, len(f.args))
- pre := ev.Value(f.args[1])
- toks := splitSpacesBytes(ev.Value(f.args[2]))
+ abuf := newBuf()
+ fargs := ev.args(abuf, f.args[1:]...)
+ pre := fargs[0]
+ toks := splitSpacesBytes(fargs[1])
sw := ssvWriter{w: w}
for _, tok := range toks {
sw.Write(pre)
// Use |w| not to append extra ' '.
w.Write(tok)
}
+ freeBuf(abuf)
}
type funcRealpath struct{ fclosure }
@@ -480,7 +555,10 @@ func (f *funcRealpath) Eval(w io.Writer, ev *Evaluator) {
ev.hasIO = true
return
}
- names := splitSpaces(string(ev.Value(f.args[1])))
+ abuf := newBuf()
+ f.args[1].Eval(abuf, ev)
+ names := splitSpaces(abuf.String())
+ freeBuf(abuf)
sw := ssvWriter{w: w}
for _, name := range names {
name, err := filepath.Abs(name)
@@ -506,7 +584,10 @@ func (f *funcAbspath) Eval(w io.Writer, ev *Evaluator) {
ev.hasIO = true
return
}
- names := splitSpaces(string(ev.Value(f.args[1])))
+ abuf := newBuf()
+ f.args[1].Eval(abuf, ev)
+ names := splitSpaces(abuf.String())
+ freeBuf(abuf)
sw := ssvWriter{w: w}
for _, name := range names {
name, err := filepath.Abs(name)
@@ -524,11 +605,14 @@ type funcIf struct{ fclosure }
func (f *funcIf) Arity() int { return 3 }
func (f *funcIf) Eval(w io.Writer, ev *Evaluator) {
assertArity("if", 2, len(f.args))
- cond := ev.Value(f.args[1])
- if len(cond) != 0 {
+ abuf := newBuf()
+ f.args[1].Eval(abuf, ev)
+ if len(abuf.Bytes()) != 0 {
+ freeBuf(abuf)
f.args[2].Eval(w, ev)
return
}
+ freeBuf(abuf)
if len(f.args) > 3 {
f.args[3].Eval(w, ev)
}
@@ -539,14 +623,19 @@ type funcAnd struct{ fclosure }
func (f *funcAnd) Arity() int { return 0 }
func (f *funcAnd) Eval(w io.Writer, ev *Evaluator) {
assertArity("and", 0, len(f.args))
+ abuf := newBuf()
var cond []byte
for _, arg := range f.args[1:] {
- cond = ev.Value(arg)
+ abuf.Reset()
+ arg.Eval(abuf, ev)
+ cond = abuf.Bytes()
if len(cond) == 0 {
+ freeBuf(abuf)
return
}
}
w.Write(cond)
+ freeBuf(abuf)
}
type funcOr struct{ fclosure }
@@ -554,13 +643,18 @@ type funcOr struct{ fclosure }
func (f *funcOr) Arity() int { return 0 }
func (f *funcOr) Eval(w io.Writer, ev *Evaluator) {
assertArity("or", 0, len(f.args))
+ abuf := newBuf()
for _, arg := range f.args[1:] {
- cond := ev.Value(arg)
+ abuf.Reset()
+ arg.Eval(abuf, ev)
+ cond := abuf.Bytes()
if len(cond) != 0 {
w.Write(cond)
+ freeBuf(abuf)
return
}
}
+ freeBuf(abuf)
}
// http://www.gnu.org/software/make/manual/make.html#Shell-Function
@@ -574,10 +668,13 @@ func (f *funcShell) Eval(w io.Writer, ev *Evaluator) {
ev.hasIO = true
return
}
- arg := ev.Value(f.args[1])
+ abuf := newBuf()
+ f.args[1].Eval(abuf, ev)
+ arg := abuf.String()
+ freeBuf(abuf)
shellVar := ev.LookupVar("SHELL")
// TODO: Should be Eval, not String.
- cmdline := []string{shellVar.String(), "-c", string(arg)}
+ cmdline := []string{shellVar.String(), "-c", arg}
cmd := exec.Cmd{
Path: cmdline[0],
Args: cmdline,
@@ -599,7 +696,9 @@ type funcCall struct{ fclosure }
func (f *funcCall) Arity() int { return 0 }
func (f *funcCall) Eval(w io.Writer, ev *Evaluator) {
- variable := ev.Value(f.args[1])
+ abuf := newBuf()
+ fargs := ev.args(abuf, f.args[1:]...)
+ variable := fargs[0]
Log("call %q variable %q", f.args[1], variable)
v := ev.LookupVar(string(variable))
// Evalualte all arguments first before we modify the table.
@@ -610,10 +709,10 @@ func (f *funcCall) Eval(w io.Writer, ev *Evaluator) {
// the built-in function is always invoked (even if a make variable
// by that name also exists).
- for i, arg := range f.args[2:] {
- // f.args[2] will be $1.
- args = append(args, tmpval(ev.Value(arg)))
- Log("call $%d: %q=>%q", i+1, arg, args[i+1])
+ for i, arg := range fargs[1:] {
+ // f.args[2]=>args[1] will be $1.
+ args = append(args, tmpval(arg))
+ Log("call $%d: %q=>%q", i+1, arg, fargs[i+1])
}
oldParams := ev.paramVars
ev.paramVars = args
@@ -638,6 +737,7 @@ func (f *funcCall) Eval(w io.Writer, ev *Evaluator) {
}
ev.paramVars = oldParams
Log("call %q variable %q return %q", f.args[1], variable, buf.Bytes())
+ freeBuf(abuf)
}
// http://www.gnu.org/software/make/manual/make.html#Value-Function
@@ -656,8 +756,10 @@ type funcEval struct{ fclosure }
func (f *funcEval) Arity() int { return 1 }
func (f *funcEval) Eval(w io.Writer, ev *Evaluator) {
assertArity("eval", 1, len(f.args))
- s := ev.Value(f.args[1])
- Log("eval %q at %s:%d", string(s), ev.filename, ev.lineno)
+ abuf := newBuf()
+ f.args[1].Eval(abuf, ev)
+ s := abuf.Bytes()
+ Log("eval %q at %s:%d", s, ev.filename, ev.lineno)
mk, err := ParseMakefileBytes(s, ev.filename, ev.lineno)
if err != nil {
panic(err)
@@ -666,6 +768,7 @@ func (f *funcEval) Eval(w io.Writer, ev *Evaluator) {
for _, stmt := range mk.stmts {
ev.eval(stmt)
}
+ freeBuf(abuf)
}
func (f *funcEval) Compact() Value {
@@ -738,7 +841,7 @@ func (f *funcNop) Eval(io.Writer, *Evaluator) {}
func (f *funcNop) Serialize() SerializableVar {
return SerializableVar{
Type: "funcNop",
- V: f.expr,
+ V: f.expr,
}
}
@@ -775,7 +878,9 @@ func (f *funcEvalAssign) String() string {
}
func (f *funcEvalAssign) Eval(w io.Writer, ev *Evaluator) {
- rhs := trimLeftSpaceBytes(ev.Value(f.rhs))
+ var abuf bytes.Buffer
+ f.rhs.Eval(&abuf, ev)
+ rhs := trimLeftSpaceBytes(abuf.Bytes())
var rvalue Var
switch f.op {
case ":=":
@@ -785,7 +890,9 @@ func (f *funcEvalAssign) Eval(w io.Writer, ev *Evaluator) {
if err != nil {
panic(fmt.Sprintf("eval assign error: %q: %v", f.String(), err))
}
- rvalue = SimpleVar{value: tmpval(ev.Value(expr)), origin: "file"}
+ abuf.Reset()
+ expr.Eval(&abuf, ev)
+ rvalue = SimpleVar{value: tmpval(abuf.Bytes()), origin: "file"}
case "=":
rvalue = RecursiveVar{expr: tmpval(rhs), origin: "file"}
case "+=":
@@ -847,8 +954,10 @@ func (f *funcInfo) Eval(w io.Writer, ev *Evaluator) {
ev.hasIO = true
return
}
- arg := ev.Value(f.args[1])
- fmt.Printf("%s\n", arg)
+ abuf := newBuf()
+ f.args[1].Eval(abuf, ev)
+ fmt.Printf("%s\n", abuf.String())
+ freeBuf(abuf)
}
type funcWarning struct{ fclosure }
@@ -860,8 +969,10 @@ func (f *funcWarning) Eval(w io.Writer, ev *Evaluator) {
ev.hasIO = true
return
}
- arg := ev.Value(f.args[1])
- fmt.Printf("%s:%d: %s\n", ev.filename, ev.lineno, arg)
+ abuf := newBuf()
+ f.args[1].Eval(abuf, ev)
+ fmt.Printf("%s:%d: %s\n", ev.filename, ev.lineno, abuf.String())
+ freeBuf(abuf)
}
type funcError struct{ fclosure }
@@ -873,8 +984,10 @@ func (f *funcError) Eval(w io.Writer, ev *Evaluator) {
ev.hasIO = true
return
}
- arg := ev.Value(f.args[1])
- Error(ev.filename, ev.lineno, "*** %s.", arg)
+ abuf := newBuf()
+ f.args[1].Eval(abuf, ev)
+ Error(ev.filename, ev.lineno, "*** %s.", abuf.String())
+ freeBuf(abuf)
}
// http://www.gnu.org/software/make/manual/make.html#Foreach-Function
@@ -884,8 +997,10 @@ func (f *funcForeach) Arity() int { return 3 }
func (f *funcForeach) Eval(w io.Writer, ev *Evaluator) {
assertArity("foreach", 3, len(f.args))
- varname := string(ev.Value(f.args[1]))
- list := ev.Values(f.args[2])
+ abuf := newBuf()
+ fargs := ev.args(abuf, f.args[1], f.args[2])
+ varname := string(fargs[0])
+ list := splitSpacesBytes(fargs[1])
text := f.args[3]
restore := ev.outVars.save(varname)
defer restore()
@@ -893,7 +1008,7 @@ func (f *funcForeach) Eval(w io.Writer, ev *Evaluator) {
for _, word := range list {
ev.outVars.Assign(varname,
SimpleVar{
- value: word,
+ value: tmpval(word),
origin: "automatic",
})
if space {
@@ -902,4 +1017,5 @@ func (f *funcForeach) Eval(w io.Writer, ev *Evaluator) {
text.Eval(w, ev)
space = true
}
+ freeBuf(abuf)
}