1// 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
15package kati
16
17import (
18	"bytes"
19	"fmt"
20	"io"
21	"os"
22	"os/exec"
23	"path/filepath"
24	"sort"
25	"strconv"
26	"strings"
27	"time"
28
29	"github.com/golang/glog"
30)
31
32// mkFunc is a make function.
33// http://www.gnu.org/software/make/manual/make.html#Functions
34
35// mkFunc is make builtin function.
36type mkFunc interface {
37	// 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.
43	// the first argument will be "(funcname", or "{funcname".
44	AddArg(Value)
45
46	Value
47}
48
49var (
50	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{} },
63
64		"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{} },
74
75		"if":  func() mkFunc { return &funcIf{} },
76		"and": func() mkFunc { return &funcAnd{} },
77		"or":  func() mkFunc { return &funcOr{} },
78
79		"value": func() mkFunc { return &funcValue{} },
80
81		"eval": func() mkFunc { return &funcEval{} },
82
83		"shell":   func() mkFunc { return &funcShell{} },
84		"call":    func() mkFunc { return &funcCall{} },
85		"foreach": func() mkFunc { return &funcForeach{} },
86
87		"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{} },
92	}
93)
94
95type 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 {
105	if n-1 < req {
106		return arityError{narg: n - 1, name: name}
107	}
108	return nil
109}
110
111func numericValueForFunc(v string) (int, bool) {
112	n, err := strconv.Atoi(v)
113	if err != nil || n < 0 {
114		return n, false
115	}
116	return n, true
117}
118
119func formatCommandOutput(out []byte) []byte {
120	out = bytes.TrimRight(out, "\n")
121	out = bytes.Replace(out, []byte{'\n'}, []byte{' '}, -1)
122	return out
123}
124
125type fclosure struct {
126	// args[0] is "(funcname", or "{funcname".
127	args []Value
128}
129
130func (c *fclosure) AddArg(v Value) {
131	c.args = append(c.args, v)
132}
133
134func (c *fclosure) String() string {
135	if len(c.args) == 0 {
136		return "$(func)"
137	}
138	arg0 := c.args[0].String()
139	if arg0 == "" {
140		return "$(func )"
141	}
142	cp := closeParen(arg0[0])
143	if cp == 0 {
144		return "${func }"
145	}
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}
152
153func (c *fclosure) serialize() serializableVar {
154	r := serializableVar{Type: "func"}
155	for _, a := range c.args {
156		r.Children = append(r.Children, a.serialize())
157	}
158	return r
159}
160
161func (c *fclosure) dump(d *dumpbuf) {
162	d.Byte(valueTypeFunc)
163	for _, a := range c.args {
164		a.dump(d)
165	}
166}
167
168// http://www.gnu.org/software/make/manual/make.html#Text-Functions
169type funcSubst struct{ fclosure }
170
171func (f *funcSubst) Arity() int { return 3 }
172func (f *funcSubst) Eval(w evalWriter, ev *Evaluator) error {
173	err := assertArity("subst", 3, len(f.args))
174	if err != nil {
175		return err
176	}
177	abuf := newEbuf()
178	fargs, err := ev.args(abuf, f.args[1:]...)
179	if err != nil {
180		return err
181	}
182	t := time.Now()
183	from := fargs[0]
184	to := fargs[1]
185	text := fargs[2]
186	glog.V(1).Infof("subst from:%q to:%q text:%q", from, to, text)
187	if len(from) == 0 {
188		w.Write(text)
189		w.Write(to)
190	} else {
191		w.Write(bytes.Replace(text, from, to, -1))
192	}
193	abuf.release()
194	stats.add("funcbody", "subst", t)
195	return nil
196}
197
198type funcPatsubst struct{ fclosure }
199
200func (f *funcPatsubst) Arity() int { return 3 }
201func (f *funcPatsubst) Eval(w evalWriter, ev *Evaluator) error {
202	err := assertArity("patsubst", 3, len(f.args))
203	if err != nil {
204		return err
205	}
206	abuf := newEbuf()
207	fargs, err := ev.args(abuf, f.args[1], f.args[2])
208	if err != nil {
209		return err
210	}
211	wb := newWbuf()
212	err = f.args[3].Eval(wb, ev)
213	if err != nil {
214		return err
215	}
216	t := time.Now()
217	pat := fargs[0]
218	repl := fargs[1]
219	for _, word := range wb.words {
220		pre, subst, post := substPatternBytes(pat, repl, word)
221		var sword []byte
222		sword = append(sword, pre...)
223		if subst != nil {
224			sword = append(sword, subst...)
225			sword = append(sword, post...)
226		}
227		w.writeWord(sword)
228	}
229	abuf.release()
230	wb.release()
231	stats.add("funcbody", "patsubst", t)
232	return nil
233}
234
235type funcStrip struct{ fclosure }
236
237func (f *funcStrip) Arity() int { return 1 }
238func (f *funcStrip) Eval(w evalWriter, ev *Evaluator) error {
239	err := assertArity("strip", 1, len(f.args))
240	if err != nil {
241		return err
242	}
243	wb := newWbuf()
244	err = f.args[1].Eval(wb, ev)
245	if err != nil {
246		return err
247	}
248	t := time.Now()
249	for _, word := range wb.words {
250		w.writeWord(word)
251	}
252	wb.release()
253	stats.add("funcbody", "strip", t)
254	return nil
255}
256
257type funcFindstring struct{ fclosure }
258
259func (f *funcFindstring) Arity() int { return 2 }
260func (f *funcFindstring) Eval(w evalWriter, ev *Evaluator) error {
261	err := assertArity("findstring", 2, len(f.args))
262	if err != nil {
263		return err
264	}
265	abuf := newEbuf()
266	fargs, err := ev.args(abuf, f.args[1:]...)
267	if err != nil {
268		return err
269	}
270	t := time.Now()
271	find := fargs[0]
272	text := fargs[1]
273	if bytes.Index(text, find) >= 0 {
274		w.Write(find)
275	}
276	abuf.release()
277	stats.add("funcbody", "findstring", t)
278	return nil
279}
280
281type funcFilter struct{ fclosure }
282
283func (f *funcFilter) Arity() int { return 2 }
284func (f *funcFilter) Eval(w evalWriter, ev *Evaluator) error {
285	err := assertArity("filter", 2, len(f.args))
286	if err != nil {
287		return err
288	}
289	patternsBuffer := newWbuf()
290	err = f.args[1].Eval(patternsBuffer, ev)
291	if err != nil {
292		return err
293	}
294	textBuffer := newWbuf()
295	err = f.args[2].Eval(textBuffer, ev)
296	if err != nil {
297		return err
298	}
299	t := time.Now()
300	for _, text := range textBuffer.words {
301		for _, pat := range patternsBuffer.words {
302			if matchPatternBytes(pat, text) {
303				w.writeWord(text)
304			}
305		}
306	}
307	patternsBuffer.release()
308	textBuffer.release()
309	stats.add("funcbody", "filter", t)
310	return nil
311}
312
313type funcFilterOut struct{ fclosure }
314
315func (f *funcFilterOut) Arity() int { return 2 }
316func (f *funcFilterOut) Eval(w evalWriter, ev *Evaluator) error {
317	err := assertArity("filter-out", 2, len(f.args))
318	if err != nil {
319		return err
320	}
321	patternsBuffer := newWbuf()
322	err = f.args[1].Eval(patternsBuffer, ev)
323	if err != nil {
324		return err
325	}
326	textBuffer := newWbuf()
327	err = f.args[2].Eval(textBuffer, ev)
328	if err != nil {
329		return err
330	}
331	t := time.Now()
332Loop:
333	for _, text := range textBuffer.words {
334		for _, pat := range patternsBuffer.words {
335			if matchPatternBytes(pat, text) {
336				continue Loop
337			}
338		}
339		w.writeWord(text)
340	}
341	patternsBuffer.release()
342	textBuffer.release()
343	stats.add("funcbody", "filter-out", t)
344	return err
345}
346
347type funcSort struct{ fclosure }
348
349func (f *funcSort) Arity() int { return 1 }
350func (f *funcSort) Eval(w evalWriter, ev *Evaluator) error {
351	err := assertArity("sort", 1, len(f.args))
352	if err != nil {
353		return err
354	}
355	wb := newWbuf()
356	err = f.args[1].Eval(wb, ev)
357	if err != nil {
358		return err
359	}
360	t := time.Now()
361	var toks []string
362	for _, tok := range wb.words {
363		toks = append(toks, string(tok))
364	}
365	wb.release()
366	sort.Strings(toks)
367
368	// Remove duplicate words.
369	var prev string
370	for _, tok := range toks {
371		if prev == tok {
372			continue
373		}
374		w.writeWordString(tok)
375		prev = tok
376	}
377	stats.add("funcbody", "sort", t)
378	return nil
379}
380
381type funcWord struct{ fclosure }
382
383func (f *funcWord) Arity() int { return 2 }
384func (f *funcWord) Eval(w evalWriter, ev *Evaluator) error {
385	err := assertArity("word", 2, len(f.args))
386	if err != nil {
387		return err
388	}
389	abuf := newEbuf()
390	err = f.args[1].Eval(abuf, ev)
391	if err != nil {
392		return err
393	}
394	v := string(trimSpaceBytes(abuf.Bytes()))
395	abuf.release()
396	index, ok := numericValueForFunc(v)
397	if !ok {
398		return ev.errorf(`*** non-numeric first argument to "word" function: %q.`, v)
399	}
400	if index == 0 {
401		return ev.errorf(`*** first argument to "word" function must be greater than 0.`)
402	}
403	wb := newWbuf()
404	err = f.args[2].Eval(wb, ev)
405	if err != nil {
406		return err
407	}
408	t := time.Now()
409	if index-1 < len(wb.words) {
410		w.writeWord(wb.words[index-1])
411	}
412	wb.release()
413	stats.add("funcbody", "word", t)
414	return err
415}
416
417type funcWordlist struct{ fclosure }
418
419func (f *funcWordlist) Arity() int { return 3 }
420func (f *funcWordlist) Eval(w evalWriter, ev *Evaluator) error {
421	err := assertArity("wordlist", 3, len(f.args))
422	if err != nil {
423		return err
424	}
425	abuf := newEbuf()
426	fargs, err := ev.args(abuf, f.args[1], f.args[2])
427	if err != nil {
428		return err
429	}
430	t := time.Now()
431	v := string(trimSpaceBytes(fargs[0]))
432	si, ok := numericValueForFunc(v)
433	if !ok {
434		return ev.errorf(`*** non-numeric first argument to "wordlist" function: %q.`, v)
435	}
436	if si == 0 {
437		return ev.errorf(`*** invalid first argument to "wordlist" function: %s`, f.args[1])
438	}
439	v = string(trimSpaceBytes(fargs[1]))
440	ei, ok := numericValueForFunc(v)
441	if !ok {
442		return ev.errorf(`*** non-numeric second argument to "wordlist" function: %q.`, v)
443	}
444	abuf.release()
445
446	wb := newWbuf()
447	err = f.args[3].Eval(wb, ev)
448	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)
454		}
455	}
456	wb.release()
457	stats.add("funcbody", "wordlist", t)
458	return nil
459}
460
461type funcWords struct{ fclosure }
462
463func (f *funcWords) Arity() int { return 1 }
464func (f *funcWords) Eval(w evalWriter, ev *Evaluator) error {
465	err := assertArity("words", 1, len(f.args))
466	if err != nil {
467		return err
468	}
469	wb := newWbuf()
470	err = f.args[1].Eval(wb, ev)
471	if err != nil {
472		return err
473	}
474	t := time.Now()
475	n := len(wb.words)
476	wb.release()
477	w.writeWordString(strconv.Itoa(n))
478	stats.add("funcbody", "words", t)
479	return nil
480}
481
482type funcFirstword struct{ fclosure }
483
484func (f *funcFirstword) Arity() int { return 1 }
485func (f *funcFirstword) Eval(w evalWriter, ev *Evaluator) error {
486	err := assertArity("firstword", 1, len(f.args))
487	if err != nil {
488		return err
489	}
490	wb := newWbuf()
491	err = f.args[1].Eval(wb, ev)
492	if err != nil {
493		return err
494	}
495	t := time.Now()
496	if len(wb.words) > 0 {
497		w.writeWord(wb.words[0])
498	}
499	wb.release()
500	stats.add("funcbody", "firstword", t)
501	return nil
502}
503
504type funcLastword struct{ fclosure }
505
506func (f *funcLastword) Arity() int { return 1 }
507func (f *funcLastword) Eval(w evalWriter, ev *Evaluator) error {
508	err := assertArity("lastword", 1, len(f.args))
509	if err != nil {
510		return err
511	}
512	wb := newWbuf()
513	err = f.args[1].Eval(wb, ev)
514	if err != nil {
515		return err
516	}
517	t := time.Now()
518	if len(wb.words) > 0 {
519		w.writeWord(wb.words[len(wb.words)-1])
520	}
521	wb.release()
522	stats.add("funcbody", "lastword", t)
523	return err
524}
525
526// 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 }
531func (f *funcJoin) Eval(w evalWriter, ev *Evaluator) error {
532	err := assertArity("join", 2, len(f.args))
533	if err != nil {
534		return err
535	}
536	wb1 := newWbuf()
537	err = f.args[1].Eval(wb1, ev)
538	if err != nil {
539		return err
540	}
541	wb2 := newWbuf()
542	err = f.args[2].Eval(wb2, ev)
543	if err != nil {
544		return err
545	}
546	t := time.Now()
547	for i := 0; i < len(wb1.words) || i < len(wb2.words); i++ {
548		var word []byte
549		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		}
555		w.writeWord(word)
556	}
557	wb1.release()
558	wb2.release()
559	stats.add("funcbody", "join", t)
560	return nil
561}
562
563type funcWildcard struct{ fclosure }
564
565func (f *funcWildcard) Arity() int { return 1 }
566func (f *funcWildcard) Eval(w evalWriter, ev *Evaluator) error {
567	err := assertArity("wildcard", 1, len(f.args))
568	if err != nil {
569		return err
570	}
571	wb := newWbuf()
572	err = f.args[1].Eval(wb, ev)
573	if err != nil {
574		return err
575	}
576	te := traceEvent.begin("wildcard", tmpval(wb.Bytes()), traceEventMain)
577	// Note GNU make does not delay the execution of $(wildcard) so we
578	// do not need to check avoid_io here.
579	t := time.Now()
580	for _, word := range wb.words {
581		pat := string(word)
582		err = wildcard(w, pat)
583		if err != nil {
584			return err
585		}
586	}
587	wb.release()
588	traceEvent.end(te)
589	stats.add("funcbody", "wildcard", t)
590	return nil
591}
592
593type funcDir struct{ fclosure }
594
595func (f *funcDir) Arity() int { return 1 }
596func (f *funcDir) Eval(w evalWriter, ev *Evaluator) error {
597	err := assertArity("dir", 1, len(f.args))
598	if err != nil {
599		return err
600	}
601	wb := newWbuf()
602	err = f.args[1].Eval(wb, ev)
603	if err != nil {
604		return err
605	}
606	t := time.Now()
607	for _, word := range wb.words {
608		name := filepath.Dir(string(word))
609		if name == "/" {
610			w.writeWordString(name)
611			continue
612		}
613		w.writeWordString(name + string(filepath.Separator))
614	}
615	wb.release()
616	stats.add("funcbody", "dir", t)
617	return nil
618}
619
620type funcNotdir struct{ fclosure }
621
622func (f *funcNotdir) Arity() int { return 1 }
623func (f *funcNotdir) Eval(w evalWriter, ev *Evaluator) error {
624	err := assertArity("notdir", 1, len(f.args))
625	if err != nil {
626		return err
627	}
628	wb := newWbuf()
629	err = f.args[1].Eval(wb, ev)
630	if err != nil {
631		return err
632	}
633	t := time.Now()
634	for _, word := range wb.words {
635		name := string(word)
636		if name == string(filepath.Separator) {
637			w.writeWord([]byte{}) // separator
638			continue
639		}
640		w.writeWordString(filepath.Base(name))
641	}
642	wb.release()
643	stats.add("funcbody", "notdir", t)
644	return nil
645}
646
647type funcSuffix struct{ fclosure }
648
649func (f *funcSuffix) Arity() int { return 1 }
650func (f *funcSuffix) Eval(w evalWriter, ev *Evaluator) error {
651	err := assertArity("suffix", 1, len(f.args))
652	if err != nil {
653		return err
654	}
655	wb := newWbuf()
656	err = f.args[1].Eval(wb, ev)
657	if err != nil {
658		return err
659	}
660	t := time.Now()
661	for _, word := range wb.words {
662		tok := string(word)
663		e := filepath.Ext(tok)
664		if len(e) > 0 {
665			w.writeWordString(e)
666		}
667	}
668	wb.release()
669	stats.add("funcbody", "suffix", t)
670	return err
671}
672
673type funcBasename struct{ fclosure }
674
675func (f *funcBasename) Arity() int { return 1 }
676func (f *funcBasename) Eval(w evalWriter, ev *Evaluator) error {
677	err := assertArity("basename", 1, len(f.args))
678	if err != nil {
679		return err
680	}
681	wb := newWbuf()
682	err = f.args[1].Eval(wb, ev)
683	if err != nil {
684		return err
685	}
686	t := time.Now()
687	for _, word := range wb.words {
688		tok := string(word)
689		e := stripExt(tok)
690		w.writeWordString(e)
691	}
692	wb.release()
693	stats.add("funcbody", "basename", t)
694	return nil
695}
696
697type funcAddsuffix struct{ fclosure }
698
699func (f *funcAddsuffix) Arity() int { return 2 }
700func (f *funcAddsuffix) Eval(w evalWriter, ev *Evaluator) error {
701	err := assertArity("addsuffix", 2, len(f.args))
702	if err != nil {
703		return err
704	}
705	abuf := newEbuf()
706	err = f.args[1].Eval(abuf, ev)
707	if err != nil {
708		return err
709	}
710	wb := newWbuf()
711	err = f.args[2].Eval(wb, ev)
712	if err != nil {
713		return err
714	}
715	t := time.Now()
716	suf := abuf.Bytes()
717	for _, word := range wb.words {
718		var name []byte
719		name = append(name, word...)
720		name = append(name, suf...)
721		w.writeWord(name)
722	}
723	wb.release()
724	abuf.release()
725	stats.add("funcbody", "addsuffix", t)
726	return err
727}
728
729type funcAddprefix struct{ fclosure }
730
731func (f *funcAddprefix) Arity() int { return 2 }
732func (f *funcAddprefix) Eval(w evalWriter, ev *Evaluator) error {
733	err := assertArity("addprefix", 2, len(f.args))
734	if err != nil {
735		return err
736	}
737	abuf := newEbuf()
738	err = f.args[1].Eval(abuf, ev)
739	if err != nil {
740		return err
741	}
742	pre := abuf.Bytes()
743	wb := newWbuf()
744	err = f.args[2].Eval(wb, ev)
745	if err != nil {
746		return err
747	}
748	t := time.Now()
749	for _, word := range wb.words {
750		var name []byte
751		name = append(name, pre...)
752		name = append(name, word...)
753		w.writeWord(name)
754	}
755	wb.release()
756	abuf.release()
757	stats.add("funcbody", "addprefix", t)
758	return err
759}
760
761type funcRealpath struct{ fclosure }
762
763func (f *funcRealpath) Arity() int { return 1 }
764func (f *funcRealpath) Eval(w evalWriter, ev *Evaluator) error {
765	err := assertArity("realpath", 1, len(f.args))
766	if err != nil {
767		return err
768	}
769	wb := newWbuf()
770	err = f.args[1].Eval(wb, ev)
771	if err != nil {
772		return err
773	}
774	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
781	t := time.Now()
782	for _, word := range wb.words {
783		name := string(word)
784		name, err := filepath.Abs(name)
785		if err != nil {
786			glog.Warningf("abs %q: %v", name, err)
787			continue
788		}
789		name, err = filepath.EvalSymlinks(name)
790		if err != nil {
791			glog.Warningf("realpath %q: %v", name, err)
792			continue
793		}
794		w.writeWordString(name)
795	}
796	wb.release()
797	stats.add("funcbody", "realpath", t)
798	return err
799}
800
801type funcAbspath struct{ fclosure }
802
803func (f *funcAbspath) Arity() int { return 1 }
804func (f *funcAbspath) Eval(w evalWriter, ev *Evaluator) error {
805	err := assertArity("abspath", 1, len(f.args))
806	if err != nil {
807		return err
808	}
809	wb := newWbuf()
810	err = f.args[1].Eval(wb, ev)
811	if err != nil {
812		return err
813	}
814	t := time.Now()
815	for _, word := range wb.words {
816		name := string(word)
817		name, err := filepath.Abs(name)
818		if err != nil {
819			glog.Warningf("abs %q: %v", name, err)
820			continue
821		}
822		w.writeWordString(name)
823	}
824	wb.release()
825	stats.add("funcbody", "abspath", t)
826	return nil
827}
828
829// http://www.gnu.org/software/make/manual/make.html#Conditional-Functions
830type funcIf struct{ fclosure }
831
832func (f *funcIf) Arity() int { return 3 }
833func (f *funcIf) Eval(w evalWriter, ev *Evaluator) error {
834	err := assertArity("if", 2, len(f.args))
835	if err != nil {
836		return err
837	}
838	abuf := newEbuf()
839	err = f.args[1].Eval(abuf, ev)
840	if err != nil {
841		return err
842	}
843	if len(abuf.Bytes()) != 0 {
844		abuf.release()
845		return f.args[2].Eval(w, ev)
846	}
847	abuf.release()
848	if len(f.args) > 3 {
849		return f.args[3].Eval(w, ev)
850	}
851	return nil
852}
853
854type funcAnd struct{ fclosure }
855
856func (f *funcAnd) Arity() int { return 0 }
857func (f *funcAnd) Eval(w evalWriter, ev *Evaluator) error {
858	err := assertArity("and", 0, len(f.args))
859	if err != nil {
860		return nil
861	}
862	abuf := newEbuf()
863	var cond []byte
864	for _, arg := range f.args[1:] {
865		abuf.Reset()
866		err = arg.Eval(abuf, ev)
867		if err != nil {
868			return err
869		}
870		cond = abuf.Bytes()
871		if len(cond) == 0 {
872			abuf.release()
873			return nil
874		}
875	}
876	w.Write(cond)
877	abuf.release()
878	return nil
879}
880
881type funcOr struct{ fclosure }
882
883func (f *funcOr) Arity() int { return 0 }
884func (f *funcOr) Eval(w evalWriter, ev *Evaluator) error {
885	err := assertArity("or", 0, len(f.args))
886	if err != nil {
887		return err
888	}
889	abuf := newEbuf()
890	for _, arg := range f.args[1:] {
891		abuf.Reset()
892		err = arg.Eval(abuf, ev)
893		if err != nil {
894			return err
895		}
896		cond := abuf.Bytes()
897		if len(cond) != 0 {
898			w.Write(cond)
899			abuf.release()
900			return nil
901		}
902	}
903	abuf.release()
904	return nil
905}
906
907// http://www.gnu.org/software/make/manual/make.html#Shell-Function
908type funcShell struct{ fclosure }
909
910func (f *funcShell) Arity() int { return 1 }
911
912// 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	}
925	glog.Infof("has no IO - evaluate now: %s", s)
926	return true
927}
928
929func (f *funcShell) Eval(w evalWriter, ev *Evaluator) error {
930	err := assertArity("shell", 1, len(f.args))
931	if err != nil {
932		return err
933	}
934	abuf := newEbuf()
935	err = f.args[1].Eval(abuf, ev)
936	if err != nil {
937		return err
938	}
939	if ev.avoidIO && !hasNoIoInShellScript(abuf.Bytes()) {
940		te := traceEvent.begin("shell", tmpval(abuf.Bytes()), traceEventMain)
941		ev.hasIO = true
942		io.WriteString(w, "$(")
943		w.Write(abuf.Bytes())
944		writeByte(w, ')')
945		traceEvent.end(te)
946		abuf.release()
947		return nil
948	}
949	arg := abuf.String()
950	abuf.release()
951	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
962	shellVar, err := ev.EvaluateVar("SHELL")
963	if err != nil {
964		return err
965	}
966	cmdline := []string{shellVar, "-c", arg}
967	if glog.V(1) {
968		glog.Infof("shell %q", cmdline)
969	}
970	cmd := exec.Cmd{
971		Path:   cmdline[0],
972		Args:   cmdline,
973		Stderr: os.Stderr,
974	}
975	te := traceEvent.begin("shell", literal(arg), traceEventMain)
976	out, err := cmd.Output()
977	shellStats.add(time.Since(te.t))
978	if err != nil {
979		glog.Warningf("$(shell %q) failed: %q", arg, err)
980	}
981	w.Write(formatCommandOutput(out))
982	traceEvent.end(te)
983	return nil
984}
985
986func (f *funcShell) Compact() Value {
987	if len(f.args)-1 < 1 {
988		return f
989	}
990	if !UseShellBuiltins {
991		return f
992	}
993
994	var exp expr
995	switch v := f.args[1].(type) {
996	case expr:
997		exp = v
998	default:
999		exp = expr{v}
1000	}
1001	if UseShellBuiltins {
1002		// hack for android
1003		for _, sb := range shBuiltins {
1004			if v, ok := matchExpr(exp, sb.pattern); ok {
1005				glog.Infof("shell compact apply %s for %s", sb.name, exp)
1006				return sb.compact(f, v)
1007			}
1008		}
1009		glog.V(1).Infof("shell compact no match: %s", exp)
1010	}
1011	return f
1012}
1013
1014// 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
1019func (f *funcCall) Eval(w evalWriter, ev *Evaluator) error {
1020	abuf := newEbuf()
1021	fargs, err := ev.args(abuf, f.args[1:]...)
1022	if err != nil {
1023		return err
1024	}
1025	varname := fargs[0]
1026	variable := string(varname)
1027	te := traceEvent.begin("call", literal(variable), traceEventMain)
1028	if glog.V(1) {
1029		glog.Infof("call %q variable %q", f.args[1], variable)
1030	}
1031	v := ev.LookupVar(variable)
1032	// Evalualte all arguments first before we modify the table.
1033	// 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)
1044	// $0 is variable.
1045	args[0] = tmpval(varname)
1046	// 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
1050	for i, arg := range fargs[1:] {
1051		// f.args[2]=>args[1] will be $1.
1052		args[i+1] = tmpval(arg)
1053		if glog.V(1) {
1054			glog.Infof("call $%d: %q=>%q", i+1, arg, fargs[i+1])
1055		}
1056	}
1057	oldParams := ev.paramVars
1058	ev.paramVars = args
1059
1060	var buf bytes.Buffer
1061	if glog.V(1) {
1062		w = &ssvWriter{Writer: io.MultiWriter(w, &buf)}
1063	}
1064	err = v.Eval(w, ev)
1065	if err != nil {
1066		return err
1067	}
1068	ev.paramVars = oldParams
1069	traceEvent.end(te)
1070	if glog.V(1) {
1071		glog.Infof("call %q variable %q return %q", f.args[1], variable, buf.Bytes())
1072	}
1073	abuf.release()
1074	return nil
1075}
1076
1077// http://www.gnu.org/software/make/manual/make.html#Value-Function
1078type funcValue struct{ fclosure }
1079
1080func (f *funcValue) Arity() int { return 1 }
1081func (f *funcValue) Eval(w evalWriter, ev *Evaluator) error {
1082	err := assertArity("value", 1, len(f.args))
1083	if err != nil {
1084		return err
1085	}
1086	abuf := newEbuf()
1087	err = f.args[1].Eval(abuf, ev)
1088	if err != nil {
1089		return err
1090	}
1091	v := ev.LookupVar(abuf.String())
1092	abuf.release()
1093	io.WriteString(w, v.String())
1094	return nil
1095}
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 }
1101func (f *funcEval) Eval(w evalWriter, ev *Evaluator) error {
1102	err := assertArity("eval", 1, len(f.args))
1103	if err != nil {
1104		return err
1105	}
1106	abuf := newEbuf()
1107	err = f.args[1].Eval(abuf, ev)
1108	if err != nil {
1109		return err
1110	}
1111	s := abuf.Bytes()
1112	glog.V(1).Infof("eval %v=>%q at %s", f.args[1], s, ev.srcpos)
1113	mk, err := parseMakefileBytes(trimSpaceBytes(s), ev.srcpos)
1114	if err != nil {
1115		return ev.errorf("%v", err)
1116	}
1117
1118	for _, stmt := range mk.stmts {
1119		err = ev.eval(stmt)
1120		if err != nil {
1121			return err
1122		}
1123	}
1124	abuf.release()
1125	return nil
1126}
1127
1128func (f *funcEval) Compact() Value {
1129	if len(f.args)-1 < 1 {
1130		return f
1131	}
1132	switch arg := f.args[1].(type) {
1133	case literal, tmpval:
1134	case expr:
1135		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))
1143				var rhs expr
1144				if rhsprefix != literal("") {
1145					rhs = append(rhs, rhsprefix)
1146				}
1147				rhs = append(rhs, arg[1:]...)
1148				glog.V(1).Infof("eval assign %#v => lhs:%q op:%q rhs:%#v", f, lhs, op, rhs)
1149				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)).
1157		return f
1158	default:
1159		return f
1160	}
1161	arg := f.args[1].String()
1162	arg = stripComment(arg)
1163	if arg == "" || strings.TrimSpace(arg) == "" {
1164		return &funcNop{expr: f.String()}
1165	}
1166	f.args[1] = literal(arg)
1167	lhs, op, rhs, ok := parseAssignLiteral(f.args[1].String())
1168	if ok {
1169		return &funcEvalAssign{
1170			lhs: lhs,
1171			op:  op,
1172			rhs: rhs,
1173		}
1174	}
1175	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
1194func (f *funcNop) String() string                    { return f.expr }
1195func (f *funcNop) Eval(evalWriter, *Evaluator) error { return nil }
1196func (f *funcNop) serialize() serializableVar {
1197	return serializableVar{
1198		Type: "funcNop",
1199		V:    f.expr,
1200	}
1201}
1202func (f *funcNop) dump(d *dumpbuf) {
1203	d.Byte(valueTypeNop)
1204}
1205
1206func 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
1228type funcEvalAssign struct {
1229	lhs string
1230	op  string
1231	rhs Value
1232}
1233
1234func (f *funcEvalAssign) String() string {
1235	return fmt.Sprintf("$(eval %s %s %s)", f.lhs, f.op, f.rhs)
1236}
1237
1238func (f *funcEvalAssign) Eval(w evalWriter, ev *Evaluator) error {
1239	var abuf evalBuffer
1240	abuf.resetSep()
1241	err := f.rhs.Eval(&abuf, ev)
1242	if err != nil {
1243		return err
1244	}
1245	rhs := trimLeftSpaceBytes(abuf.Bytes())
1246	glog.V(1).Infof("evalAssign: lhs=%q rhs=%s %q", f.lhs, f.rhs, rhs)
1247	var rvalue Var
1248	switch f.op {
1249	case ":=":
1250		// TODO(ukai): compute parsed expr in Compact when f.rhs is
1251		// literal? e.g. literal("$(foo)") => varref{literal("foo")}.
1252		exp, _, err := parseExpr(rhs, nil, parseOp{})
1253		if err != nil {
1254			return ev.errorf("eval assign error: %q: %v", f.String(), err)
1255		}
1256		vbuf := newEbuf()
1257		err = exp.Eval(vbuf, ev)
1258		if err != nil {
1259			return err
1260		}
1261		rvalue = &simpleVar{value: []string{vbuf.String()}, origin: "file"}
1262		vbuf.release()
1263	case "=":
1264		rvalue = &recursiveVar{expr: tmpval(rhs), origin: "file"}
1265	case "+=":
1266		prev := ev.LookupVar(f.lhs)
1267		if prev.IsDefined() {
1268			rvalue, err = prev.Append(ev, string(rhs))
1269			if err != nil {
1270				return err
1271			}
1272		} else {
1273			rvalue = &recursiveVar{expr: tmpval(rhs), origin: "file"}
1274		}
1275	case "?=":
1276		prev := ev.LookupVar(f.lhs)
1277		if prev.IsDefined() {
1278			return nil
1279		}
1280		rvalue = &recursiveVar{expr: tmpval(rhs), origin: "file"}
1281	}
1282	if glog.V(1) {
1283		glog.Infof("Eval ASSIGN: %s=%q (flavor:%q)", f.lhs, rvalue, rvalue.Flavor())
1284	}
1285	ev.outVars.Assign(f.lhs, rvalue)
1286	return nil
1287}
1288
1289func (f *funcEvalAssign) serialize() serializableVar {
1290	return serializableVar{
1291		Type: "funcEvalAssign",
1292		Children: []serializableVar{
1293			serializableVar{V: f.lhs},
1294			serializableVar{V: f.op},
1295			f.rhs.serialize(),
1296		},
1297	}
1298}
1299
1300func (f *funcEvalAssign) dump(d *dumpbuf) {
1301	d.Byte(valueTypeAssign)
1302	d.Str(f.lhs)
1303	d.Str(f.op)
1304	f.rhs.dump(d)
1305}
1306
1307// http://www.gnu.org/software/make/manual/make.html#Origin-Function
1308type funcOrigin struct{ fclosure }
1309
1310func (f *funcOrigin) Arity() int { return 1 }
1311func (f *funcOrigin) Eval(w evalWriter, ev *Evaluator) error {
1312	err := assertArity("origin", 1, len(f.args))
1313	if err != nil {
1314		return err
1315	}
1316	abuf := newEbuf()
1317	err = f.args[1].Eval(abuf, ev)
1318	if err != nil {
1319		return err
1320	}
1321	v := ev.LookupVar(abuf.String())
1322	abuf.release()
1323	io.WriteString(w, v.Origin())
1324	return nil
1325}
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 }
1331func (f *funcFlavor) Eval(w evalWriter, ev *Evaluator) error {
1332	err := assertArity("flavor", 1, len(f.args))
1333	if err != nil {
1334		return err
1335	}
1336	abuf := newEbuf()
1337	err = f.args[1].Eval(abuf, ev)
1338	if err != nil {
1339		return err
1340	}
1341	v := ev.LookupVar(abuf.String())
1342	abuf.release()
1343	io.WriteString(w, v.Flavor())
1344	return nil
1345}
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 }
1351func (f *funcInfo) Eval(w evalWriter, ev *Evaluator) error {
1352	err := assertArity("info", 1, len(f.args))
1353	if err != nil {
1354		return err
1355	}
1356	abuf := newEbuf()
1357	err = f.args[1].Eval(abuf, ev)
1358	if err != nil {
1359		return err
1360	}
1361	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	}
1368	fmt.Printf("%s\n", abuf.String())
1369	abuf.release()
1370	return nil
1371}
1372
1373type funcWarning struct{ fclosure }
1374
1375func (f *funcWarning) Arity() int { return 1 }
1376func (f *funcWarning) Eval(w evalWriter, ev *Evaluator) error {
1377	err := assertArity("warning", 1, len(f.args))
1378	if err != nil {
1379		return err
1380	}
1381	abuf := newEbuf()
1382	err = f.args[1].Eval(abuf, ev)
1383	if err != nil {
1384		return err
1385	}
1386	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	}
1393	fmt.Printf("%s: %s\n", ev.srcpos, abuf.String())
1394	abuf.release()
1395	return nil
1396}
1397
1398type funcError struct{ fclosure }
1399
1400func (f *funcError) Arity() int { return 1 }
1401func (f *funcError) Eval(w evalWriter, ev *Evaluator) error {
1402	err := assertArity("error", 1, len(f.args))
1403	if err != nil {
1404		return err
1405	}
1406	var abuf evalBuffer
1407	abuf.resetSep()
1408	err = f.args[1].Eval(&abuf, ev)
1409	if err != nil {
1410		return err
1411	}
1412	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	}
1419	return ev.errorf("*** %s.", abuf.String())
1420}
1421
1422// http://www.gnu.org/software/make/manual/make.html#Foreach-Function
1423type funcForeach struct{ fclosure }
1424
1425func (f *funcForeach) Arity() int { return 3 }
1426
1427func (f *funcForeach) Eval(w evalWriter, ev *Evaluator) error {
1428	err := assertArity("foreach", 3, len(f.args))
1429	if err != nil {
1430		return err
1431	}
1432	abuf := newEbuf()
1433	err = f.args[1].Eval(abuf, ev)
1434	if err != nil {
1435		return err
1436	}
1437	varname := string(abuf.Bytes())
1438	abuf.release()
1439	wb := newWbuf()
1440	err = f.args[2].Eval(wb, ev)
1441	if err != nil {
1442		return err
1443	}
1444	text := f.args[3]
1445	ov := ev.LookupVar(varname)
1446	space := false
1447	for _, word := range wb.words {
1448		ev.outVars.Assign(varname, &automaticVar{value: word})
1449		if space {
1450			writeByte(w, ' ')
1451		}
1452		err = text.Eval(w, ev)
1453		if err != nil {
1454			return err
1455		}
1456		space = true
1457	}
1458	wb.release()
1459	av := ev.LookupVar(varname)
1460	if _, ok := av.(*automaticVar); ok {
1461		ev.outVars.Assign(varname, ov)
1462	}
1463	return nil
1464}
1465