blob: bdc560d911f0a6cabc87e36c59c7a612d19478e2 [file] [log] [blame]
Shinichiro Hamajib69bf8a2015-06-10 14:52:06 +09001// 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
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +090015package kati
Fumitoshi Ukaif2f84562015-03-30 19:47:45 +090016
17import (
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090018 "bytes"
Fumitoshi Ukaif2f84562015-03-30 19:47:45 +090019 "fmt"
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090020 "io"
Shinichiro Hamajie7aafb02015-04-09 18:23:46 +090021 "os"
Fumitoshi Ukaif2f84562015-03-30 19:47:45 +090022 "os/exec"
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +090023 "path/filepath"
Shinichiro Hamaji13b30d92015-04-03 14:42:21 +090024 "sort"
Shinichiro Hamajie708a9d2015-04-03 14:34:35 +090025 "strconv"
Fumitoshi Ukaif2f84562015-03-30 19:47:45 +090026 "strings"
Fumitoshi Ukai586b02a2015-05-08 00:23:10 +090027 "time"
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +090028
29 "github.com/golang/glog"
Fumitoshi Ukaif2f84562015-03-30 19:47:45 +090030)
31
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090032// mkFunc is a make function.
Fumitoshi Ukaif2f84562015-03-30 19:47:45 +090033// http://www.gnu.org/software/make/manual/make.html#Functions
Fumitoshi Ukaie520f262015-03-31 17:27:03 +090034
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090035// mkFunc is make builtin function.
36type mkFunc interface {
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090037 // Arity is max function's arity.
38 // ',' will not be handled as argument separator more than arity.
39 // 0 means varargs.
40 Arity() int
41
42 // AddArg adds value as an argument.
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +090043 // the first argument will be "(funcname", or "{funcname".
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090044 AddArg(Value)
45
46 Value
47}
48
49var (
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090050 funcMap = map[string]func() mkFunc{
51 "patsubst": func() mkFunc { return &funcPatsubst{} },
52 "strip": func() mkFunc { return &funcStrip{} },
53 "subst": func() mkFunc { return &funcSubst{} },
54 "findstring": func() mkFunc { return &funcFindstring{} },
55 "filter": func() mkFunc { return &funcFilter{} },
56 "filter-out": func() mkFunc { return &funcFilterOut{} },
57 "sort": func() mkFunc { return &funcSort{} },
58 "word": func() mkFunc { return &funcWord{} },
59 "wordlist": func() mkFunc { return &funcWordlist{} },
60 "words": func() mkFunc { return &funcWords{} },
61 "firstword": func() mkFunc { return &funcFirstword{} },
62 "lastword": func() mkFunc { return &funcLastword{} },
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +090063
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090064 "join": func() mkFunc { return &funcJoin{} },
65 "wildcard": func() mkFunc { return &funcWildcard{} },
66 "dir": func() mkFunc { return &funcDir{} },
67 "notdir": func() mkFunc { return &funcNotdir{} },
68 "suffix": func() mkFunc { return &funcSuffix{} },
69 "basename": func() mkFunc { return &funcBasename{} },
70 "addsuffix": func() mkFunc { return &funcAddsuffix{} },
71 "addprefix": func() mkFunc { return &funcAddprefix{} },
72 "realpath": func() mkFunc { return &funcRealpath{} },
73 "abspath": func() mkFunc { return &funcAbspath{} },
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +090074
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090075 "if": func() mkFunc { return &funcIf{} },
76 "and": func() mkFunc { return &funcAnd{} },
77 "or": func() mkFunc { return &funcOr{} },
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +090078
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090079 "value": func() mkFunc { return &funcValue{} },
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +090080
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090081 "eval": func() mkFunc { return &funcEval{} },
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +090082
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090083 "shell": func() mkFunc { return &funcShell{} },
84 "call": func() mkFunc { return &funcCall{} },
85 "foreach": func() mkFunc { return &funcForeach{} },
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +090086
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090087 "origin": func() mkFunc { return &funcOrigin{} },
88 "flavor": func() mkFunc { return &funcFlavor{} },
89 "info": func() mkFunc { return &funcInfo{} },
90 "warning": func() mkFunc { return &funcWarning{} },
91 "error": func() mkFunc { return &funcError{} },
Fumitoshi Ukai0b5e18b2015-04-03 22:57:17 +090092 }
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090093)
94
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090095type arityError struct {
96 narg int
97 name string
98}
99
100func (e arityError) Error() string {
101 return fmt.Sprintf("*** insufficient number of arguments (%d) to function `%s'.", e.narg, e.name)
102}
103
104func assertArity(name string, req, n int) error {
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900105 if n-1 < req {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900106 return arityError{narg: n - 1, name: name}
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900107 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900108 return nil
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900109}
110
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900111func numericValueForFunc(v string) (int, bool) {
112 n, err := strconv.Atoi(v)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900113 if err != nil || n < 0 {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900114 return n, false
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900115 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900116 return n, true
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900117}
118
Shinichiro Hamajiba6b84d2015-06-03 18:46:13 +0900119func formatCommandOutput(out []byte) []byte {
120 out = bytes.TrimRight(out, "\n")
121 out = bytes.Replace(out, []byte{'\n'}, []byte{' '}, -1)
122 return out
123}
124
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900125type fclosure struct {
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900126 // args[0] is "(funcname", or "{funcname".
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900127 args []Value
128}
129
130func (c *fclosure) AddArg(v Value) {
131 c.args = append(c.args, v)
Fumitoshi Ukai0b5e18b2015-04-03 22:57:17 +0900132}
133
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900134func (c *fclosure) String() string {
135 if len(c.args) == 0 {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900136 return "$(func)"
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900137 }
138 arg0 := c.args[0].String()
139 if arg0 == "" {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900140 return "$(func )"
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900141 }
142 cp := closeParen(arg0[0])
143 if cp == 0 {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900144 return "${func }"
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900145 }
146 var args []string
147 for _, arg := range c.args[1:] {
148 args = append(args, arg.String())
149 }
150 return fmt.Sprintf("$%s %s%c", arg0, strings.Join(args, ","), cp)
151}
Fumitoshi Ukai78781132015-04-10 17:08:40 +0900152
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900153func (c *fclosure) serialize() serializableVar {
154 r := serializableVar{Type: "func"}
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900155 for _, a := range c.args {
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900156 r.Children = append(r.Children, a.serialize())
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900157 }
158 return r
159}
160
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900161func (c *fclosure) dump(d *dumpbuf) {
162 d.Byte(valueTypeFunc)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900163 for _, a := range c.args {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900164 a.dump(d)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900165 }
166}
167
Shinichiro Hamaji4125cf42015-04-03 11:42:28 +0900168// http://www.gnu.org/software/make/manual/make.html#Text-Functions
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900169type funcSubst struct{ fclosure }
170
171func (f *funcSubst) Arity() int { return 3 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900172func (f *funcSubst) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900173 err := assertArity("subst", 3, len(f.args))
174 if err != nil {
175 return err
176 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900177 abuf := newEbuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900178 fargs, err := ev.args(abuf, f.args[1:]...)
179 if err != nil {
180 return err
181 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900182 t := time.Now()
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900183 from := fargs[0]
184 to := fargs[1]
185 text := fargs[2]
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900186 glog.V(1).Infof("subst from:%q to:%q text:%q", from, to, text)
Fumitoshi Ukaic252c6b2015-07-07 18:11:04 +0900187 if len(from) == 0 {
188 w.Write(text)
189 w.Write(to)
190 } else {
191 w.Write(bytes.Replace(text, from, to, -1))
192 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900193 abuf.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900194 stats.add("funcbody", "subst", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900195 return nil
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900196}
197
Shinichiro Hamaji98e910d2015-04-11 10:38:44 +0900198type funcPatsubst struct{ fclosure }
199
200func (f *funcPatsubst) Arity() int { return 3 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900201func (f *funcPatsubst) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900202 err := assertArity("patsubst", 3, len(f.args))
203 if err != nil {
204 return err
205 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900206 abuf := newEbuf()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900207 fargs, err := ev.args(abuf, f.args[1], f.args[2])
208 if err != nil {
209 return err
210 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900211 wb := newWbuf()
212 err = f.args[3].Eval(wb, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900213 if err != nil {
214 return err
215 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900216 t := time.Now()
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900217 pat := fargs[0]
218 repl := fargs[1]
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900219 for _, word := range wb.words {
220 pre, subst, post := substPatternBytes(pat, repl, word)
221 var sword []byte
222 sword = append(sword, pre...)
Fumitoshi Ukai77411fb2015-06-19 15:46:21 +0900223 if subst != nil {
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900224 sword = append(sword, subst...)
225 sword = append(sword, post...)
Fumitoshi Ukai77411fb2015-06-19 15:46:21 +0900226 }
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900227 w.writeWord(sword)
Shinichiro Hamaji98e910d2015-04-11 10:38:44 +0900228 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900229 abuf.release()
230 wb.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900231 stats.add("funcbody", "patsubst", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900232 return nil
Shinichiro Hamaji98e910d2015-04-11 10:38:44 +0900233}
234
235type funcStrip struct{ fclosure }
236
237func (f *funcStrip) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900238func (f *funcStrip) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900239 err := assertArity("strip", 1, len(f.args))
240 if err != nil {
241 return err
242 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900243 wb := newWbuf()
244 err = f.args[1].Eval(wb, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900245 if err != nil {
246 return err
247 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900248 t := time.Now()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900249 for _, word := range wb.words {
250 w.writeWord(word)
Shinichiro Hamajib978e112015-06-05 11:02:45 +0900251 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900252 wb.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900253 stats.add("funcbody", "strip", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900254 return nil
Shinichiro Hamaji98e910d2015-04-11 10:38:44 +0900255}
256
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900257type funcFindstring struct{ fclosure }
258
259func (f *funcFindstring) Arity() int { return 2 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900260func (f *funcFindstring) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900261 err := assertArity("findstring", 2, len(f.args))
262 if err != nil {
263 return err
264 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900265 abuf := newEbuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900266 fargs, err := ev.args(abuf, f.args[1:]...)
267 if err != nil {
268 return err
269 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900270 t := time.Now()
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900271 find := fargs[0]
272 text := fargs[1]
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900273 if bytes.Index(text, find) >= 0 {
274 w.Write(find)
275 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900276 abuf.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900277 stats.add("funcbody", "findstring", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900278 return nil
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900279}
280
281type funcFilter struct{ fclosure }
282
283func (f *funcFilter) Arity() int { return 2 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900284func (f *funcFilter) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900285 err := assertArity("filter", 2, len(f.args))
286 if err != nil {
287 return err
288 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900289 patternsBuffer := newWbuf()
290 err = f.args[1].Eval(patternsBuffer, ev)
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900291 if err != nil {
292 return err
293 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900294 textBuffer := newWbuf()
295 err = f.args[2].Eval(textBuffer, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900296 if err != nil {
297 return err
298 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900299 t := time.Now()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900300 for _, text := range textBuffer.words {
301 for _, pat := range patternsBuffer.words {
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900302 if matchPatternBytes(pat, text) {
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900303 w.writeWord(text)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900304 }
305 }
306 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900307 patternsBuffer.release()
308 textBuffer.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900309 stats.add("funcbody", "filter", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900310 return nil
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900311}
312
313type funcFilterOut struct{ fclosure }
314
315func (f *funcFilterOut) Arity() int { return 2 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900316func (f *funcFilterOut) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900317 err := assertArity("filter-out", 2, len(f.args))
318 if err != nil {
319 return err
320 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900321 patternsBuffer := newWbuf()
322 err = f.args[1].Eval(patternsBuffer, ev)
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900323 if err != nil {
324 return err
325 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900326 textBuffer := newWbuf()
327 err = f.args[2].Eval(textBuffer, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900328 if err != nil {
329 return err
330 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900331 t := time.Now()
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900332Loop:
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900333 for _, text := range textBuffer.words {
334 for _, pat := range patternsBuffer.words {
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900335 if matchPatternBytes(pat, text) {
336 continue Loop
337 }
338 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900339 w.writeWord(text)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900340 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900341 patternsBuffer.release()
342 textBuffer.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900343 stats.add("funcbody", "filter-out", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900344 return err
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900345}
346
347type funcSort struct{ fclosure }
348
349func (f *funcSort) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900350func (f *funcSort) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900351 err := assertArity("sort", 1, len(f.args))
352 if err != nil {
353 return err
354 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900355 wb := newWbuf()
356 err = f.args[1].Eval(wb, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900357 if err != nil {
358 return err
359 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900360 t := time.Now()
Fumitoshi Ukai79cfbab2015-06-18 23:28:26 +0900361 var toks []string
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900362 for _, tok := range wb.words {
363 toks = append(toks, string(tok))
Fumitoshi Ukai79cfbab2015-06-18 23:28:26 +0900364 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900365 wb.release()
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900366 sort.Strings(toks)
367
368 // Remove duplicate words.
369 var prev string
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900370 for _, tok := range toks {
Fumitoshi Ukaice14acb2015-06-19 13:54:53 +0900371 if prev == tok {
372 continue
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900373 }
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900374 w.writeWordString(tok)
Fumitoshi Ukaice14acb2015-06-19 13:54:53 +0900375 prev = tok
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900376 }
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900377 stats.add("funcbody", "sort", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900378 return nil
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900379}
380
381type funcWord struct{ fclosure }
382
383func (f *funcWord) Arity() int { return 2 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900384func (f *funcWord) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900385 err := assertArity("word", 2, len(f.args))
386 if err != nil {
387 return err
388 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900389 abuf := newEbuf()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900390 err = f.args[1].Eval(abuf, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900391 if err != nil {
392 return err
393 }
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900394 v := string(trimSpaceBytes(abuf.Bytes()))
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900395 abuf.release()
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900396 index, ok := numericValueForFunc(v)
397 if !ok {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900398 return ev.errorf(`*** non-numeric first argument to "word" function: %q.`, v)
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900399 }
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900400 if index == 0 {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900401 return ev.errorf(`*** first argument to "word" function must be greater than 0.`)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900402 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900403 wb := newWbuf()
404 err = f.args[2].Eval(wb, ev)
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900405 if err != nil {
406 return err
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900407 }
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900408 t := time.Now()
409 if index-1 < len(wb.words) {
410 w.writeWord(wb.words[index-1])
411 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900412 wb.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900413 stats.add("funcbody", "word", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900414 return err
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900415}
416
417type funcWordlist struct{ fclosure }
418
419func (f *funcWordlist) Arity() int { return 3 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900420func (f *funcWordlist) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900421 err := assertArity("wordlist", 3, len(f.args))
422 if err != nil {
423 return err
424 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900425 abuf := newEbuf()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900426 fargs, err := ev.args(abuf, f.args[1], f.args[2])
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900427 if err != nil {
428 return err
429 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900430 t := time.Now()
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900431 v := string(trimSpaceBytes(fargs[0]))
432 si, ok := numericValueForFunc(v)
433 if !ok {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900434 return ev.errorf(`*** non-numeric first argument to "wordlist" function: %q.`, v)
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900435 }
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900436 if si == 0 {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900437 return ev.errorf(`*** invalid first argument to "wordlist" function: %s`, f.args[1])
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900438 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900439 v = string(trimSpaceBytes(fargs[1]))
440 ei, ok := numericValueForFunc(v)
441 if !ok {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900442 return ev.errorf(`*** non-numeric second argument to "wordlist" function: %q.`, v)
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900443 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900444 abuf.release()
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900445
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900446 wb := newWbuf()
447 err = f.args[3].Eval(wb, ev)
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900448 if err != nil {
449 return err
450 }
451 for i, word := range wb.words {
452 if si <= i+1 && i+1 <= ei {
453 w.writeWord(word)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900454 }
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900455 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900456 wb.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900457 stats.add("funcbody", "wordlist", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900458 return nil
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900459}
460
461type funcWords struct{ fclosure }
462
463func (f *funcWords) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900464func (f *funcWords) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900465 err := assertArity("words", 1, len(f.args))
466 if err != nil {
467 return err
468 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900469 wb := newWbuf()
470 err = f.args[1].Eval(wb, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900471 if err != nil {
472 return err
473 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900474 t := time.Now()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900475 n := len(wb.words)
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900476 wb.release()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900477 w.writeWordString(strconv.Itoa(n))
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900478 stats.add("funcbody", "words", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900479 return nil
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900480}
481
482type funcFirstword struct{ fclosure }
483
484func (f *funcFirstword) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900485func (f *funcFirstword) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900486 err := assertArity("firstword", 1, len(f.args))
487 if err != nil {
488 return err
489 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900490 wb := newWbuf()
491 err = f.args[1].Eval(wb, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900492 if err != nil {
493 return err
494 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900495 t := time.Now()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900496 if len(wb.words) > 0 {
497 w.writeWord(wb.words[0])
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900498 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900499 wb.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900500 stats.add("funcbody", "firstword", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900501 return nil
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900502}
503
504type funcLastword struct{ fclosure }
505
506func (f *funcLastword) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900507func (f *funcLastword) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900508 err := assertArity("lastword", 1, len(f.args))
509 if err != nil {
510 return err
511 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900512 wb := newWbuf()
513 err = f.args[1].Eval(wb, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900514 if err != nil {
515 return err
516 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900517 t := time.Now()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900518 if len(wb.words) > 0 {
519 w.writeWord(wb.words[len(wb.words)-1])
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900520 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900521 wb.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900522 stats.add("funcbody", "lastword", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900523 return err
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900524}
525
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900526// https://www.gnu.org/software/make/manual/html_node/File-Name-Functions.html#File-Name-Functions
527
528type funcJoin struct{ fclosure }
529
530func (f *funcJoin) Arity() int { return 2 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900531func (f *funcJoin) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900532 err := assertArity("join", 2, len(f.args))
533 if err != nil {
534 return err
535 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900536 wb1 := newWbuf()
537 err = f.args[1].Eval(wb1, ev)
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900538 if err != nil {
539 return err
540 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900541 wb2 := newWbuf()
542 err = f.args[2].Eval(wb2, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900543 if err != nil {
544 return err
545 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900546 t := time.Now()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900547 for i := 0; i < len(wb1.words) || i < len(wb2.words); i++ {
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900548 var word []byte
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900549 if i < len(wb1.words) {
550 word = append(word, wb1.words[i]...)
551 }
552 if i < len(wb2.words) {
553 word = append(word, wb2.words[i]...)
554 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900555 w.writeWord(word)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900556 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900557 wb1.release()
558 wb2.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900559 stats.add("funcbody", "join", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900560 return nil
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900561}
562
563type funcWildcard struct{ fclosure }
564
565func (f *funcWildcard) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900566func (f *funcWildcard) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900567 err := assertArity("wildcard", 1, len(f.args))
568 if err != nil {
569 return err
570 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900571 wb := newWbuf()
572 err = f.args[1].Eval(wb, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900573 if err != nil {
574 return err
575 }
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900576 te := traceEvent.begin("wildcard", tmpval(wb.Bytes()), traceEventMain)
Fumitoshi Ukai17c85752015-07-28 16:10:00 +0900577 // Note GNU make does not delay the execution of $(wildcard) so we
578 // do not need to check avoid_io here.
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900579 t := time.Now()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900580 for _, word := range wb.words {
581 pat := string(word)
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900582 err = wildcard(w, pat)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900583 if err != nil {
584 return err
585 }
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900586 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900587 wb.release()
Fumitoshi Ukai432a2422015-06-11 15:16:29 +0900588 traceEvent.end(te)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900589 stats.add("funcbody", "wildcard", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900590 return nil
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900591}
592
593type funcDir struct{ fclosure }
594
595func (f *funcDir) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900596func (f *funcDir) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900597 err := assertArity("dir", 1, len(f.args))
598 if err != nil {
599 return err
600 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900601 wb := newWbuf()
602 err = f.args[1].Eval(wb, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900603 if err != nil {
604 return err
605 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900606 t := time.Now()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900607 for _, word := range wb.words {
608 name := filepath.Dir(string(word))
Shinichiro Hamaji37626b62015-04-21 16:59:23 +0900609 if name == "/" {
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900610 w.writeWordString(name)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900611 continue
Shinichiro Hamaji37626b62015-04-21 16:59:23 +0900612 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900613 w.writeWordString(name + string(filepath.Separator))
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900614 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900615 wb.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900616 stats.add("funcbody", "dir", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900617 return nil
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900618}
619
620type funcNotdir struct{ fclosure }
621
622func (f *funcNotdir) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900623func (f *funcNotdir) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900624 err := assertArity("notdir", 1, len(f.args))
625 if err != nil {
626 return err
627 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900628 wb := newWbuf()
629 err = f.args[1].Eval(wb, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900630 if err != nil {
631 return err
632 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900633 t := time.Now()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900634 for _, word := range wb.words {
635 name := string(word)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900636 if name == string(filepath.Separator) {
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900637 w.writeWord([]byte{}) // separator
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900638 continue
639 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900640 w.writeWordString(filepath.Base(name))
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900641 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900642 wb.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900643 stats.add("funcbody", "notdir", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900644 return nil
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900645}
646
647type funcSuffix struct{ fclosure }
648
649func (f *funcSuffix) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900650func (f *funcSuffix) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900651 err := assertArity("suffix", 1, len(f.args))
652 if err != nil {
653 return err
654 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900655 wb := newWbuf()
656 err = f.args[1].Eval(wb, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900657 if err != nil {
658 return err
659 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900660 t := time.Now()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900661 for _, word := range wb.words {
662 tok := string(word)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900663 e := filepath.Ext(tok)
664 if len(e) > 0 {
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900665 w.writeWordString(e)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900666 }
667 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900668 wb.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900669 stats.add("funcbody", "suffix", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900670 return err
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900671}
672
673type funcBasename struct{ fclosure }
674
675func (f *funcBasename) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900676func (f *funcBasename) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900677 err := assertArity("basename", 1, len(f.args))
678 if err != nil {
679 return err
680 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900681 wb := newWbuf()
682 err = f.args[1].Eval(wb, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900683 if err != nil {
684 return err
685 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900686 t := time.Now()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900687 for _, word := range wb.words {
688 tok := string(word)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900689 e := stripExt(tok)
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900690 w.writeWordString(e)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900691 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900692 wb.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900693 stats.add("funcbody", "basename", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900694 return nil
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900695}
696
697type funcAddsuffix struct{ fclosure }
698
699func (f *funcAddsuffix) Arity() int { return 2 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900700func (f *funcAddsuffix) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900701 err := assertArity("addsuffix", 2, len(f.args))
702 if err != nil {
703 return err
704 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900705 abuf := newEbuf()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900706 err = f.args[1].Eval(abuf, ev)
707 if err != nil {
708 return err
709 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900710 wb := newWbuf()
711 err = f.args[2].Eval(wb, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900712 if err != nil {
713 return err
714 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900715 t := time.Now()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900716 suf := abuf.Bytes()
717 for _, word := range wb.words {
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900718 var name []byte
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900719 name = append(name, word...)
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900720 name = append(name, suf...)
721 w.writeWord(name)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900722 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900723 wb.release()
724 abuf.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900725 stats.add("funcbody", "addsuffix", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900726 return err
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900727}
728
729type funcAddprefix struct{ fclosure }
730
731func (f *funcAddprefix) Arity() int { return 2 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900732func (f *funcAddprefix) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900733 err := assertArity("addprefix", 2, len(f.args))
734 if err != nil {
735 return err
736 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900737 abuf := newEbuf()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900738 err = f.args[1].Eval(abuf, ev)
739 if err != nil {
740 return err
741 }
742 pre := abuf.Bytes()
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900743 wb := newWbuf()
744 err = f.args[2].Eval(wb, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900745 if err != nil {
746 return err
747 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900748 t := time.Now()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900749 for _, word := range wb.words {
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900750 var name []byte
751 name = append(name, pre...)
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900752 name = append(name, word...)
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900753 w.writeWord(name)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900754 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900755 wb.release()
756 abuf.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900757 stats.add("funcbody", "addprefix", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900758 return err
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900759}
760
761type funcRealpath struct{ fclosure }
762
763func (f *funcRealpath) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900764func (f *funcRealpath) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900765 err := assertArity("realpath", 1, len(f.args))
766 if err != nil {
767 return err
768 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900769 wb := newWbuf()
770 err = f.args[1].Eval(wb, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900771 if err != nil {
772 return err
773 }
Fumitoshi Ukai651a82d2015-07-28 16:16:48 +0900774 if ev.avoidIO {
775 fmt.Fprintf(w, "$(realpath %s 2>/dev/null)", string(wb.Bytes()))
776 ev.hasIO = true
777 wb.release()
778 return nil
779 }
780
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900781 t := time.Now()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900782 for _, word := range wb.words {
783 name := string(word)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900784 name, err := filepath.Abs(name)
785 if err != nil {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900786 glog.Warningf("abs %q: %v", name, err)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900787 continue
788 }
789 name, err = filepath.EvalSymlinks(name)
790 if err != nil {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900791 glog.Warningf("realpath %q: %v", name, err)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900792 continue
793 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900794 w.writeWordString(name)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900795 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900796 wb.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900797 stats.add("funcbody", "realpath", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900798 return err
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900799}
800
801type funcAbspath struct{ fclosure }
802
803func (f *funcAbspath) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900804func (f *funcAbspath) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900805 err := assertArity("abspath", 1, len(f.args))
806 if err != nil {
807 return err
808 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900809 wb := newWbuf()
810 err = f.args[1].Eval(wb, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900811 if err != nil {
812 return err
813 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900814 t := time.Now()
Fumitoshi Ukai18262502015-07-07 15:20:25 +0900815 for _, word := range wb.words {
816 name := string(word)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900817 name, err := filepath.Abs(name)
818 if err != nil {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900819 glog.Warningf("abs %q: %v", name, err)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900820 continue
821 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900822 w.writeWordString(name)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900823 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900824 wb.release()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900825 stats.add("funcbody", "abspath", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900826 return nil
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900827}
828
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900829// http://www.gnu.org/software/make/manual/make.html#Conditional-Functions
830type funcIf struct{ fclosure }
831
832func (f *funcIf) Arity() int { return 3 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900833func (f *funcIf) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900834 err := assertArity("if", 2, len(f.args))
835 if err != nil {
836 return err
837 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900838 abuf := newEbuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900839 err = f.args[1].Eval(abuf, ev)
840 if err != nil {
841 return err
842 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900843 if len(abuf.Bytes()) != 0 {
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900844 abuf.release()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900845 return f.args[2].Eval(w, ev)
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900846 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900847 abuf.release()
Fumitoshi Ukaie27a25d2015-04-18 00:31:01 +0900848 if len(f.args) > 3 {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900849 return f.args[3].Eval(w, ev)
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900850 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900851 return nil
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900852}
853
854type funcAnd struct{ fclosure }
855
856func (f *funcAnd) Arity() int { return 0 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900857func (f *funcAnd) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900858 err := assertArity("and", 0, len(f.args))
859 if err != nil {
860 return nil
861 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900862 abuf := newEbuf()
Shinichiro Hamaji2216dd62015-04-11 13:44:39 +0900863 var cond []byte
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900864 for _, arg := range f.args[1:] {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900865 abuf.Reset()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900866 err = arg.Eval(abuf, ev)
867 if err != nil {
868 return err
869 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900870 cond = abuf.Bytes()
Shinichiro Hamaji2216dd62015-04-11 13:44:39 +0900871 if len(cond) == 0 {
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900872 abuf.release()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900873 return nil
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900874 }
875 }
Shinichiro Hamaji2216dd62015-04-11 13:44:39 +0900876 w.Write(cond)
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900877 abuf.release()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900878 return nil
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900879}
880
881type funcOr struct{ fclosure }
882
883func (f *funcOr) Arity() int { return 0 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900884func (f *funcOr) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900885 err := assertArity("or", 0, len(f.args))
886 if err != nil {
887 return err
888 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900889 abuf := newEbuf()
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900890 for _, arg := range f.args[1:] {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900891 abuf.Reset()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900892 err = arg.Eval(abuf, ev)
893 if err != nil {
894 return err
895 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900896 cond := abuf.Bytes()
Shinichiro Hamaji2216dd62015-04-11 13:44:39 +0900897 if len(cond) != 0 {
898 w.Write(cond)
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900899 abuf.release()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900900 return nil
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900901 }
902 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900903 abuf.release()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900904 return nil
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900905}
906
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900907// http://www.gnu.org/software/make/manual/make.html#Shell-Function
908type funcShell struct{ fclosure }
909
910func (f *funcShell) Arity() int { return 1 }
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900911
Shinichiro Hamajic0095e32015-05-27 18:49:06 +0900912// A hack for Android build. We need to evaluate things like $((3+4))
913// when we emit ninja file, because the result of such expressions
914// will be passed to other make functions.
915// TODO: Maybe we should modify Android's Makefile and remove this
916// workaround. It would be also nice if we can detect things like
917// this.
918func hasNoIoInShellScript(s []byte) bool {
919 if len(s) == 0 {
920 return true
921 }
922 if !bytes.HasPrefix(s, []byte("echo $((")) || s[len(s)-1] != ')' {
923 return false
924 }
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900925 glog.Infof("has no IO - evaluate now: %s", s)
Shinichiro Hamajic0095e32015-05-27 18:49:06 +0900926 return true
927}
928
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900929func (f *funcShell) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900930 err := assertArity("shell", 1, len(f.args))
931 if err != nil {
932 return err
933 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900934 abuf := newEbuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900935 err = f.args[1].Eval(abuf, ev)
936 if err != nil {
937 return err
938 }
Shinichiro Hamajic0095e32015-05-27 18:49:06 +0900939 if ev.avoidIO && !hasNoIoInShellScript(abuf.Bytes()) {
Fumitoshi Ukai83410132015-06-15 14:50:07 +0900940 te := traceEvent.begin("shell", tmpval(abuf.Bytes()), traceEventMain)
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +0900941 ev.hasIO = true
Fumitoshi Ukai145598a2015-06-19 10:08:17 +0900942 io.WriteString(w, "$(")
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +0900943 w.Write(abuf.Bytes())
Fumitoshi Ukai145598a2015-06-19 10:08:17 +0900944 writeByte(w, ')')
Fumitoshi Ukai432a2422015-06-11 15:16:29 +0900945 traceEvent.end(te)
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900946 abuf.release()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900947 return nil
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +0900948 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900949 arg := abuf.String()
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900950 abuf.release()
Fumitoshi Ukai0547db62015-07-29 16:20:59 +0900951 if bc, err := parseBuiltinCommand(arg); err != nil {
952 glog.V(1).Infof("sh builtin: %v", err)
953 } else {
954 glog.Info("use sh builtin:", arg)
955 glog.V(2).Infof("builtin command: %#v", bc)
956 te := traceEvent.begin("sh-builtin", literal(arg), traceEventMain)
957 bc.run(w)
958 traceEvent.end(te)
959 return nil
960 }
961
Fumitoshi Ukaic54e0252015-07-08 12:10:40 +0900962 shellVar, err := ev.EvaluateVar("SHELL")
963 if err != nil {
964 return err
965 }
966 cmdline := []string{shellVar, "-c", arg}
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900967 if glog.V(1) {
968 glog.Infof("shell %q", cmdline)
Fumitoshi Ukai44ae8cf2015-06-24 16:44:15 +0900969 }
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900970 cmd := exec.Cmd{
971 Path: cmdline[0],
972 Args: cmdline,
973 Stderr: os.Stderr,
974 }
Fumitoshi Ukai83410132015-06-15 14:50:07 +0900975 te := traceEvent.begin("shell", literal(arg), traceEventMain)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900976 out, err := cmd.Output()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900977 shellStats.add(time.Since(te.t))
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900978 if err != nil {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900979 glog.Warningf("$(shell %q) failed: %q", arg, err)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900980 }
Shinichiro Hamajiba6b84d2015-06-03 18:46:13 +0900981 w.Write(formatCommandOutput(out))
Fumitoshi Ukai432a2422015-06-11 15:16:29 +0900982 traceEvent.end(te)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900983 return nil
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900984}
985
Fumitoshi Ukai106fb792015-06-09 10:37:35 +0900986func (f *funcShell) Compact() Value {
987 if len(f.args)-1 < 1 {
988 return f
989 }
Fumitoshi Ukai0547db62015-07-29 16:20:59 +0900990 if !UseShellBuiltins {
Fumitoshi Ukai106fb792015-06-09 10:37:35 +0900991 return f
992 }
993
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900994 var exp expr
Fumitoshi Ukai44ae8cf2015-06-24 16:44:15 +0900995 switch v := f.args[1].(type) {
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900996 case expr:
997 exp = v
Fumitoshi Ukai44ae8cf2015-06-24 16:44:15 +0900998 default:
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900999 exp = expr{v}
Fumitoshi Ukai106fb792015-06-09 10:37:35 +09001000 }
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +09001001 if UseShellBuiltins {
Fumitoshi Ukai4a708512015-06-11 17:15:49 +09001002 // hack for android
1003 for _, sb := range shBuiltins {
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +09001004 if v, ok := matchExpr(exp, sb.pattern); ok {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +09001005 glog.Infof("shell compact apply %s for %s", sb.name, exp)
Fumitoshi Ukai4a708512015-06-11 17:15:49 +09001006 return sb.compact(f, v)
1007 }
Fumitoshi Ukai76b609e2015-06-10 14:56:49 +09001008 }
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +09001009 glog.V(1).Infof("shell compact no match: %s", exp)
Fumitoshi Ukai76b609e2015-06-10 14:56:49 +09001010 }
Fumitoshi Ukai106fb792015-06-09 10:37:35 +09001011 return f
1012}
1013
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001014// https://www.gnu.org/software/make/manual/html_node/Call-Function.html#Call-Function
1015type funcCall struct{ fclosure }
1016
1017func (f *funcCall) Arity() int { return 0 }
1018
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001019func (f *funcCall) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001020 abuf := newEbuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001021 fargs, err := ev.args(abuf, f.args[1:]...)
1022 if err != nil {
1023 return err
1024 }
Fumitoshi Ukaif543f4d2015-06-15 15:21:47 +09001025 varname := fargs[0]
1026 variable := string(varname)
Fumitoshi Ukai83410132015-06-15 14:50:07 +09001027 te := traceEvent.begin("call", literal(variable), traceEventMain)
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +09001028 if glog.V(1) {
1029 glog.Infof("call %q variable %q", f.args[1], variable)
Fumitoshi Ukai5c04ad82015-06-18 16:14:04 +09001030 }
Fumitoshi Ukaif543f4d2015-06-15 15:21:47 +09001031 v := ev.LookupVar(variable)
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001032 // Evalualte all arguments first before we modify the table.
Fumitoshi Ukai612e0862015-08-10 16:09:09 +09001033 // An omitted argument should be blank, even if it's nested inside
1034 // another call statement that did have that argument passed.
1035 // see testcases/nested_call.mk
1036 arglen := len(ev.paramVars)
1037 if arglen == 0 {
1038 arglen++
1039 }
1040 if arglen < len(fargs[1:])+1 {
1041 arglen = len(fargs[1:]) + 1
1042 }
1043 args := make([]tmpval, arglen)
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +09001044 // $0 is variable.
Fumitoshi Ukai612e0862015-08-10 16:09:09 +09001045 args[0] = tmpval(varname)
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +09001046 // TODO(ukai): If variable is the name of a built-in function,
1047 // the built-in function is always invoked (even if a make variable
1048 // by that name also exists).
1049
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001050 for i, arg := range fargs[1:] {
1051 // f.args[2]=>args[1] will be $1.
Fumitoshi Ukai612e0862015-08-10 16:09:09 +09001052 args[i+1] = tmpval(arg)
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +09001053 if glog.V(1) {
1054 glog.Infof("call $%d: %q=>%q", i+1, arg, fargs[i+1])
Fumitoshi Ukai5c04ad82015-06-18 16:14:04 +09001055 }
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001056 }
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +09001057 oldParams := ev.paramVars
1058 ev.paramVars = args
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001059
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001060 var buf bytes.Buffer
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +09001061 if glog.V(1) {
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001062 w = &ssvWriter{Writer: io.MultiWriter(w, &buf)}
Fumitoshi Ukaie27a25d2015-04-18 00:31:01 +09001063 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001064 err = v.Eval(w, ev)
1065 if err != nil {
1066 return err
1067 }
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +09001068 ev.paramVars = oldParams
Fumitoshi Ukai72598e72015-06-11 15:53:09 +09001069 traceEvent.end(te)
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +09001070 if glog.V(1) {
1071 glog.Infof("call %q variable %q return %q", f.args[1], variable, buf.Bytes())
Fumitoshi Ukai5c04ad82015-06-18 16:14:04 +09001072 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001073 abuf.release()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001074 return nil
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001075}
1076
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +09001077// http://www.gnu.org/software/make/manual/make.html#Value-Function
1078type funcValue struct{ fclosure }
1079
1080func (f *funcValue) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001081func (f *funcValue) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001082 err := assertArity("value", 1, len(f.args))
1083 if err != nil {
1084 return err
1085 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001086 abuf := newEbuf()
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +09001087 err = f.args[1].Eval(abuf, ev)
1088 if err != nil {
1089 return err
1090 }
1091 v := ev.LookupVar(abuf.String())
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001092 abuf.release()
Fumitoshi Ukai145598a2015-06-19 10:08:17 +09001093 io.WriteString(w, v.String())
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001094 return nil
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +09001095}
1096
1097// http://www.gnu.org/software/make/manual/make.html#Eval-Function
1098type funcEval struct{ fclosure }
1099
1100func (f *funcEval) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001101func (f *funcEval) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001102 err := assertArity("eval", 1, len(f.args))
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +09001103 if err != nil {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001104 return err
1105 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001106 abuf := newEbuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001107 err = f.args[1].Eval(abuf, ev)
1108 if err != nil {
1109 return err
1110 }
1111 s := abuf.Bytes()
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +09001112 glog.V(1).Infof("eval %v=>%q at %s", f.args[1], s, ev.srcpos)
Fumitoshi Ukai2a2deb32015-07-08 11:46:14 +09001113 mk, err := parseMakefileBytes(trimSpaceBytes(s), ev.srcpos)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001114 if err != nil {
1115 return ev.errorf("%v", err)
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +09001116 }
1117
1118 for _, stmt := range mk.stmts {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001119 err = ev.eval(stmt)
1120 if err != nil {
1121 return err
1122 }
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +09001123 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001124 abuf.release()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001125 return nil
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +09001126}
1127
Fumitoshi Ukai9f6b6352015-04-16 16:25:09 +09001128func (f *funcEval) Compact() Value {
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +09001129 if len(f.args)-1 < 1 {
1130 return f
1131 }
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +09001132 switch arg := f.args[1].(type) {
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +09001133 case literal, tmpval:
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +09001134 case expr:
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +09001135 if len(arg) == 1 {
1136 return f
1137 }
1138 switch prefix := arg[0].(type) {
1139 case literal, tmpval:
1140 lhs, op, rhsprefix, ok := parseAssignLiteral(prefix.String())
1141 if ok {
1142 // $(eval foo = $(bar))
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +09001143 var rhs expr
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +09001144 if rhsprefix != literal("") {
1145 rhs = append(rhs, rhsprefix)
1146 }
1147 rhs = append(rhs, arg[1:]...)
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +09001148 glog.V(1).Infof("eval assign %#v => lhs:%q op:%q rhs:%#v", f, lhs, op, rhs)
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +09001149 return &funcEvalAssign{
1150 lhs: lhs,
1151 op: op,
1152 rhs: compactExpr(rhs),
1153 }
1154 }
1155 }
1156 // TODO(ukai): eval -> varassign. e.g $(eval $(foo) := $(x)).
Fumitoshi Ukai769157a2015-06-02 15:18:53 +09001157 return f
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +09001158 default:
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +09001159 return f
1160 }
1161 arg := f.args[1].String()
1162 arg = stripComment(arg)
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +09001163 if arg == "" || strings.TrimSpace(arg) == "" {
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +09001164 return &funcNop{expr: f.String()}
1165 }
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +09001166 f.args[1] = literal(arg)
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +09001167 lhs, op, rhs, ok := parseAssignLiteral(f.args[1].String())
1168 if ok {
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001169 return &funcEvalAssign{
1170 lhs: lhs,
1171 op: op,
1172 rhs: rhs,
1173 }
1174 }
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +09001175 return f
1176}
1177
1178func stripComment(arg string) string {
1179 for {
1180 i := strings.Index(arg, "#")
1181 if i < 0 {
1182 return arg
1183 }
1184 eol := strings.Index(arg[i:], "\n")
1185 if eol < 0 {
1186 return arg[:i]
1187 }
1188 arg = arg[:i] + arg[eol+1:]
1189 }
1190}
1191
1192type funcNop struct{ expr string }
1193
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001194func (f *funcNop) String() string { return f.expr }
1195func (f *funcNop) Eval(evalWriter, *Evaluator) error { return nil }
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +09001196func (f *funcNop) serialize() serializableVar {
1197 return serializableVar{
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +09001198 Type: "funcNop",
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001199 V: f.expr,
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +09001200 }
1201}
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001202func (f *funcNop) dump(d *dumpbuf) {
1203 d.Byte(valueTypeNop)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +09001204}
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +09001205
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +09001206func parseAssignLiteral(s string) (lhs, op string, rhs Value, ok bool) {
1207 eq := strings.Index(s, "=")
1208 if eq < 0 {
1209 return "", "", nil, false
1210 }
1211 // TODO(ukai): factor out parse assign?
1212 lhs = s[:eq]
1213 op = s[eq : eq+1]
1214 if eq >= 1 && (s[eq-1] == ':' || s[eq-1] == '+' || s[eq-1] == '?') {
1215 lhs = s[:eq-1]
1216 op = s[eq-1 : eq+1]
1217 }
1218 lhs = strings.TrimSpace(lhs)
1219 if strings.IndexAny(lhs, ":$") >= 0 {
1220 // target specific var, or need eval.
1221 return "", "", nil, false
1222 }
1223 r := strings.TrimLeft(s[eq+1:], " \t")
1224 rhs = literal(r)
1225 return lhs, op, rhs, true
1226}
1227
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001228type funcEvalAssign struct {
1229 lhs string
1230 op string
1231 rhs Value
1232}
1233
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001234func (f *funcEvalAssign) String() string {
1235 return fmt.Sprintf("$(eval %s %s %s)", f.lhs, f.op, f.rhs)
1236}
1237
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001238func (f *funcEvalAssign) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001239 var abuf evalBuffer
1240 abuf.resetSep()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001241 err := f.rhs.Eval(&abuf, ev)
1242 if err != nil {
1243 return err
1244 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001245 rhs := trimLeftSpaceBytes(abuf.Bytes())
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +09001246 glog.V(1).Infof("evalAssign: lhs=%q rhs=%s %q", f.lhs, f.rhs, rhs)
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001247 var rvalue Var
1248 switch f.op {
1249 case ":=":
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +09001250 // TODO(ukai): compute parsed expr in Compact when f.rhs is
1251 // literal? e.g. literal("$(foo)") => varref{literal("foo")}.
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +09001252 exp, _, err := parseExpr(rhs, nil, parseOp{})
Fumitoshi Ukaifa5e9222015-04-17 11:45:20 +09001253 if err != nil {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001254 return ev.errorf("eval assign error: %q: %v", f.String(), err)
Fumitoshi Ukaifa5e9222015-04-17 11:45:20 +09001255 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001256 vbuf := newEbuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001257 err = exp.Eval(vbuf, ev)
1258 if err != nil {
1259 return err
1260 }
Fumitoshi Ukai7655f182015-07-15 14:05:41 +09001261 rvalue = &simpleVar{value: []string{vbuf.String()}, origin: "file"}
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001262 vbuf.release()
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001263 case "=":
Fumitoshi Ukai7bf992d2015-06-25 12:42:19 +09001264 rvalue = &recursiveVar{expr: tmpval(rhs), origin: "file"}
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001265 case "+=":
1266 prev := ev.LookupVar(f.lhs)
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +09001267 if prev.IsDefined() {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001268 rvalue, err = prev.Append(ev, string(rhs))
1269 if err != nil {
1270 return err
1271 }
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001272 } else {
Fumitoshi Ukai7bf992d2015-06-25 12:42:19 +09001273 rvalue = &recursiveVar{expr: tmpval(rhs), origin: "file"}
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001274 }
1275 case "?=":
1276 prev := ev.LookupVar(f.lhs)
1277 if prev.IsDefined() {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001278 return nil
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001279 }
Fumitoshi Ukai7bf992d2015-06-25 12:42:19 +09001280 rvalue = &recursiveVar{expr: tmpval(rhs), origin: "file"}
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001281 }
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +09001282 if glog.V(1) {
1283 glog.Infof("Eval ASSIGN: %s=%q (flavor:%q)", f.lhs, rvalue, rvalue.Flavor())
Fumitoshi Ukai5c04ad82015-06-18 16:14:04 +09001284 }
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001285 ev.outVars.Assign(f.lhs, rvalue)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001286 return nil
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001287}
1288
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +09001289func (f *funcEvalAssign) serialize() serializableVar {
1290 return serializableVar{
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +09001291 Type: "funcEvalAssign",
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +09001292 Children: []serializableVar{
1293 serializableVar{V: f.lhs},
1294 serializableVar{V: f.op},
1295 f.rhs.serialize(),
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +09001296 },
1297 }
1298}
1299
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001300func (f *funcEvalAssign) dump(d *dumpbuf) {
1301 d.Byte(valueTypeAssign)
1302 d.Str(f.lhs)
1303 d.Str(f.op)
1304 f.rhs.dump(d)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +09001305}
1306
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001307// http://www.gnu.org/software/make/manual/make.html#Origin-Function
1308type funcOrigin struct{ fclosure }
1309
1310func (f *funcOrigin) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001311func (f *funcOrigin) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001312 err := assertArity("origin", 1, len(f.args))
1313 if err != nil {
1314 return err
1315 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001316 abuf := newEbuf()
Fumitoshi Ukaib64400e2015-06-30 16:06:09 +09001317 err = f.args[1].Eval(abuf, ev)
1318 if err != nil {
1319 return err
1320 }
1321 v := ev.LookupVar(abuf.String())
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001322 abuf.release()
Fumitoshi Ukai145598a2015-06-19 10:08:17 +09001323 io.WriteString(w, v.Origin())
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001324 return nil
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001325}
1326
1327// https://www.gnu.org/software/make/manual/html_node/Flavor-Function.html#Flavor-Function
1328type funcFlavor struct{ fclosure }
1329
1330func (f *funcFlavor) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001331func (f *funcFlavor) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001332 err := assertArity("flavor", 1, len(f.args))
1333 if err != nil {
1334 return err
1335 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001336 abuf := newEbuf()
Fumitoshi Ukaib64400e2015-06-30 16:06:09 +09001337 err = f.args[1].Eval(abuf, ev)
1338 if err != nil {
1339 return err
1340 }
1341 v := ev.LookupVar(abuf.String())
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001342 abuf.release()
Fumitoshi Ukai145598a2015-06-19 10:08:17 +09001343 io.WriteString(w, v.Flavor())
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001344 return nil
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001345}
1346
1347// http://www.gnu.org/software/make/manual/make.html#Make-Control-Functions
1348type funcInfo struct{ fclosure }
1349
1350func (f *funcInfo) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001351func (f *funcInfo) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001352 err := assertArity("info", 1, len(f.args))
1353 if err != nil {
1354 return err
1355 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001356 abuf := newEbuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001357 err = f.args[1].Eval(abuf, ev)
1358 if err != nil {
1359 return err
1360 }
Fumitoshi Ukaie5bf7582015-07-28 16:07:51 +09001361 if ev.avoidIO {
1362 ev.delayedOutputs = append(ev.delayedOutputs,
1363 fmt.Sprintf("echo %q", abuf.String()))
1364 ev.hasIO = true
1365 abuf.release()
1366 return nil
1367 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001368 fmt.Printf("%s\n", abuf.String())
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001369 abuf.release()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001370 return nil
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001371}
1372
1373type funcWarning struct{ fclosure }
1374
1375func (f *funcWarning) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001376func (f *funcWarning) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001377 err := assertArity("warning", 1, len(f.args))
1378 if err != nil {
1379 return err
1380 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001381 abuf := newEbuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001382 err = f.args[1].Eval(abuf, ev)
1383 if err != nil {
1384 return err
1385 }
Fumitoshi Ukaie5bf7582015-07-28 16:07:51 +09001386 if ev.avoidIO {
1387 ev.delayedOutputs = append(ev.delayedOutputs,
1388 fmt.Sprintf("echo '%s: %s' 1>&2", ev.srcpos, abuf.String()))
1389 ev.hasIO = true
1390 abuf.release()
1391 return nil
1392 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001393 fmt.Printf("%s: %s\n", ev.srcpos, abuf.String())
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001394 abuf.release()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001395 return nil
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001396}
1397
1398type funcError struct{ fclosure }
1399
1400func (f *funcError) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001401func (f *funcError) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001402 err := assertArity("error", 1, len(f.args))
1403 if err != nil {
1404 return err
1405 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001406 var abuf evalBuffer
1407 abuf.resetSep()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001408 err = f.args[1].Eval(&abuf, ev)
1409 if err != nil {
1410 return err
1411 }
Fumitoshi Ukaie5bf7582015-07-28 16:07:51 +09001412 if ev.avoidIO {
1413 ev.delayedOutputs = append(ev.delayedOutputs,
1414 fmt.Sprintf("echo '%s: *** %s.' 1>&2 && false", ev.srcpos, abuf.String()))
1415 ev.hasIO = true
1416 abuf.release()
1417 return nil
1418 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001419 return ev.errorf("*** %s.", abuf.String())
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001420}
1421
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001422// http://www.gnu.org/software/make/manual/make.html#Foreach-Function
1423type funcForeach struct{ fclosure }
1424
1425func (f *funcForeach) Arity() int { return 3 }
1426
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001427func (f *funcForeach) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001428 err := assertArity("foreach", 3, len(f.args))
1429 if err != nil {
1430 return err
1431 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001432 abuf := newEbuf()
Fumitoshi Ukai18262502015-07-07 15:20:25 +09001433 err = f.args[1].Eval(abuf, ev)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001434 if err != nil {
1435 return err
1436 }
Fumitoshi Ukai18262502015-07-07 15:20:25 +09001437 varname := string(abuf.Bytes())
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001438 abuf.release()
1439 wb := newWbuf()
1440 err = f.args[2].Eval(wb, ev)
Fumitoshi Ukai18262502015-07-07 15:20:25 +09001441 if err != nil {
1442 return err
1443 }
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +09001444 text := f.args[3]
Fumitoshi Ukai21426172015-06-30 18:02:45 +09001445 ov := ev.LookupVar(varname)
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001446 space := false
Fumitoshi Ukai18262502015-07-07 15:20:25 +09001447 for _, word := range wb.words {
Fumitoshi Ukai7bf992d2015-06-25 12:42:19 +09001448 ev.outVars.Assign(varname, &automaticVar{value: word})
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001449 if space {
Fumitoshi Ukai145598a2015-06-19 10:08:17 +09001450 writeByte(w, ' ')
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001451 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001452 err = text.Eval(w, ev)
1453 if err != nil {
1454 return err
1455 }
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001456 space = true
1457 }
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +09001458 wb.release()
Fumitoshi Ukai21426172015-06-30 18:02:45 +09001459 av := ev.LookupVar(varname)
1460 if _, ok := av.(*automaticVar); ok {
1461 ev.outVars.Assign(varname, ov)
1462 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001463 return nil
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001464}