blob: 0b962ddbdec94251fe71ca5f7b76a7e1164c69cd [file] [log] [blame]
Fumitoshi Ukaif2f84562015-03-30 19:47:45 +09001package main
2
3import (
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +09004 "bytes"
Fumitoshi Ukaif2f84562015-03-30 19:47:45 +09005 "fmt"
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +09006 "io"
Shinichiro Hamajie7aafb02015-04-09 18:23:46 +09007 "os"
Fumitoshi Ukaif2f84562015-03-30 19:47:45 +09008 "os/exec"
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +09009 "path/filepath"
Shinichiro Hamaji13b30d92015-04-03 14:42:21 +090010 "sort"
Shinichiro Hamajie708a9d2015-04-03 14:34:35 +090011 "strconv"
Fumitoshi Ukaif2f84562015-03-30 19:47:45 +090012 "strings"
Fumitoshi Ukai586b02a2015-05-08 00:23:10 +090013 "time"
Fumitoshi Ukaif2f84562015-03-30 19:47:45 +090014)
15
16// Func is a make function.
17// http://www.gnu.org/software/make/manual/make.html#Functions
Fumitoshi Ukaie520f262015-03-31 17:27:03 +090018
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090019// Func is make builtin function.
20type Func interface {
21 // Arity is max function's arity.
22 // ',' will not be handled as argument separator more than arity.
23 // 0 means varargs.
24 Arity() int
25
26 // AddArg adds value as an argument.
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +090027 // the first argument will be "(funcname", or "{funcname".
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090028 AddArg(Value)
29
30 Value
31}
32
33var (
34 funcMap = map[string]func() Func{
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +090035 "patsubst": func() Func { return &funcPatsubst{} },
36 "strip": func() Func { return &funcStrip{} },
37 "subst": func() Func { return &funcSubst{} },
38 "findstring": func() Func { return &funcFindstring{} },
39 "filter": func() Func { return &funcFilter{} },
40 "filter-out": func() Func { return &funcFilterOut{} },
41 "sort": func() Func { return &funcSort{} },
42 "word": func() Func { return &funcWord{} },
43 "wordlist": func() Func { return &funcWordlist{} },
44 "words": func() Func { return &funcWords{} },
45 "firstword": func() Func { return &funcFirstword{} },
46 "lastword": func() Func { return &funcLastword{} },
47
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +090048 "join": func() Func { return &funcJoin{} },
49 "wildcard": func() Func { return &funcWildcard{} },
50 "dir": func() Func { return &funcDir{} },
51 "notdir": func() Func { return &funcNotdir{} },
52 "suffix": func() Func { return &funcSuffix{} },
53 "basename": func() Func { return &funcBasename{} },
54 "addsuffix": func() Func { return &funcAddsuffix{} },
55 "addprefix": func() Func { return &funcAddprefix{} },
56 "realpath": func() Func { return &funcRealpath{} },
57 "abspath": func() Func { return &funcAbspath{} },
58
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +090059 "if": func() Func { return &funcIf{} },
60 "and": func() Func { return &funcAnd{} },
61 "or": func() Func { return &funcOr{} },
62
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +090063 "value": func() Func { return &funcValue{} },
64
65 "eval": func() Func { return &funcEval{} },
66
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +090067 "shell": func() Func { return &funcShell{} },
68 "call": func() Func { return &funcCall{} },
69 "foreach": func() Func { return &funcForeach{} },
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +090070
71 "origin": func() Func { return &funcOrigin{} },
72 "flavor": func() Func { return &funcFlavor{} },
73 "info": func() Func { return &funcInfo{} },
74 "warning": func() Func { return &funcWarning{} },
75 "error": func() Func { return &funcError{} },
Fumitoshi Ukai0b5e18b2015-04-03 22:57:17 +090076 }
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090077)
78
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090079func assertArity(name string, req, n int) {
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +090080 if n-1 < req {
81 panic(fmt.Sprintf("*** insufficient number of arguments (%d) to function `%s'.", n-1, name))
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090082 }
83}
84
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +090085// A space separated values writer.
86type ssvWriter struct {
87 w io.Writer
88 needsSpace bool
89}
90
91func (sw *ssvWriter) Write(b []byte) {
92 if sw.needsSpace {
93 sw.w.Write([]byte{' '})
94 }
95 sw.needsSpace = true
96 sw.w.Write(b)
97}
98
Shinichiro Hamajia1358912015-04-11 12:16:21 +090099func (sw *ssvWriter) WriteString(s string) {
100 // TODO: Ineffcient. Nice if we can remove the cast.
101 sw.Write([]byte(s))
102}
103
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900104func numericValueForFunc(v string) (int, bool) {
105 n, err := strconv.Atoi(v)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900106 if err != nil || n < 0 {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900107 return n, false
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900108 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900109 return n, true
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900110}
111
Shinichiro Hamajiba6b84d2015-06-03 18:46:13 +0900112func formatCommandOutput(out []byte) []byte {
113 out = bytes.TrimRight(out, "\n")
114 out = bytes.Replace(out, []byte{'\n'}, []byte{' '}, -1)
115 return out
116}
117
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900118type fclosure struct {
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900119 // args[0] is "(funcname", or "{funcname".
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900120 args []Value
121}
122
123func (c *fclosure) AddArg(v Value) {
124 c.args = append(c.args, v)
Fumitoshi Ukai0b5e18b2015-04-03 22:57:17 +0900125}
126
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900127func (c *fclosure) String() string {
128 if len(c.args) == 0 {
129 panic("no args in func")
130 }
131 arg0 := c.args[0].String()
132 if arg0 == "" {
133 panic(fmt.Errorf("wrong format of arg0: %q", arg0))
134 }
135 cp := closeParen(arg0[0])
136 if cp == 0 {
137 panic(fmt.Errorf("wrong format of arg0: %q", arg0))
138 }
139 var args []string
140 for _, arg := range c.args[1:] {
141 args = append(args, arg.String())
142 }
143 return fmt.Sprintf("$%s %s%c", arg0, strings.Join(args, ","), cp)
144}
Fumitoshi Ukai78781132015-04-10 17:08:40 +0900145
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900146func (c *fclosure) Serialize() SerializableVar {
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900147 r := SerializableVar{Type: "func"}
148 for _, a := range c.args {
149 r.Children = append(r.Children, a.Serialize())
150 }
151 return r
152}
153
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900154func (c *fclosure) Dump(w io.Writer) {
155 dumpByte(w, VALUE_TYPE_FUNC)
156 for _, a := range c.args {
157 a.Dump(w)
158 }
159}
160
Shinichiro Hamaji4125cf42015-04-03 11:42:28 +0900161// http://www.gnu.org/software/make/manual/make.html#Text-Functions
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900162type funcSubst struct{ fclosure }
163
164func (f *funcSubst) Arity() int { return 3 }
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900165func (f *funcSubst) Eval(w io.Writer, ev *Evaluator) {
166 assertArity("subst", 3, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900167 abuf := newBuf()
168 fargs := ev.args(abuf, f.args[1:]...)
169 from := fargs[0]
170 to := fargs[1]
171 text := fargs[2]
Fumitoshi Ukaibb79a9d2015-04-02 12:46:54 +0900172 Log("subst from:%q to:%q text:%q", from, to, text)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900173 w.Write(bytes.Replace(text, from, to, -1))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900174 freeBuf(abuf)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900175}
176
Shinichiro Hamaji98e910d2015-04-11 10:38:44 +0900177type funcPatsubst struct{ fclosure }
178
179func (f *funcPatsubst) Arity() int { return 3 }
180func (f *funcPatsubst) Eval(w io.Writer, ev *Evaluator) {
181 assertArity("patsubst", 3, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900182 abuf := newBuf()
183 fargs := ev.args(abuf, f.args[1:]...)
184 pat := fargs[0]
185 repl := fargs[1]
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900186 ws := newWordScanner(fargs[2])
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900187 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900188 for ws.Scan() {
189 t := substPatternBytes(pat, repl, ws.Bytes())
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900190 sw.Write(t)
Shinichiro Hamaji98e910d2015-04-11 10:38:44 +0900191 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900192 freeBuf(abuf)
Shinichiro Hamaji98e910d2015-04-11 10:38:44 +0900193}
194
195type funcStrip struct{ fclosure }
196
197func (f *funcStrip) Arity() int { return 1 }
198func (f *funcStrip) Eval(w io.Writer, ev *Evaluator) {
199 assertArity("strip", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900200 abuf := newBuf()
201 f.args[1].Eval(abuf, ev)
Shinichiro Hamajib978e112015-06-05 11:02:45 +0900202 ws := newWordScanner(abuf.Bytes())
203 sw := ssvWriter{w: w}
204 for ws.Scan() {
205 sw.Write(ws.Bytes())
206 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900207 freeBuf(abuf)
Shinichiro Hamaji98e910d2015-04-11 10:38:44 +0900208}
209
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900210type funcFindstring struct{ fclosure }
211
212func (f *funcFindstring) Arity() int { return 2 }
213func (f *funcFindstring) Eval(w io.Writer, ev *Evaluator) {
214 assertArity("findstring", 2, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900215 abuf := newBuf()
216 fargs := ev.args(abuf, f.args[1:]...)
217 find := fargs[0]
218 text := fargs[1]
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900219 if bytes.Index(text, find) >= 0 {
220 w.Write(find)
221 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900222 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900223}
224
225type funcFilter struct{ fclosure }
226
227func (f *funcFilter) Arity() int { return 2 }
228func (f *funcFilter) Eval(w io.Writer, ev *Evaluator) {
229 assertArity("filter", 2, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900230 abuf := newBuf()
231 fargs := ev.args(abuf, f.args[1:]...)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900232 var patterns [][]byte
233 ws := newWordScanner(fargs[0])
234 for ws.Scan() {
235 patterns = append(patterns, ws.Bytes())
236 }
237 ws = newWordScanner(fargs[1])
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900238 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900239 for ws.Scan() {
240 text := ws.Bytes()
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900241 for _, pat := range patterns {
242 if matchPatternBytes(pat, text) {
243 sw.Write(text)
244 }
245 }
246 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900247 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900248}
249
250type funcFilterOut struct{ fclosure }
251
252func (f *funcFilterOut) Arity() int { return 2 }
253func (f *funcFilterOut) Eval(w io.Writer, ev *Evaluator) {
254 assertArity("filter-out", 2, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900255 abuf := newBuf()
256 fargs := ev.args(abuf, f.args[1:]...)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900257 var patterns [][]byte
258 ws := newWordScanner(fargs[0])
259 for ws.Scan() {
260 patterns = append(patterns, ws.Bytes())
261 }
262 ws = newWordScanner(fargs[1])
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900263 sw := ssvWriter{w: w}
264Loop:
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900265 for ws.Scan() {
266 text := ws.Bytes()
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900267 for _, pat := range patterns {
268 if matchPatternBytes(pat, text) {
269 continue Loop
270 }
271 }
272 sw.Write(text)
273 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900274 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900275}
276
277type funcSort struct{ fclosure }
278
279func (f *funcSort) Arity() int { return 1 }
280func (f *funcSort) Eval(w io.Writer, ev *Evaluator) {
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900281 assertArity("sort", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900282 abuf := newBuf()
283 f.args[1].Eval(abuf, ev)
284 toks := splitSpaces(abuf.String())
285 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900286 sort.Strings(toks)
287
288 // Remove duplicate words.
289 var prev string
290 sw := ssvWriter{w: w}
291 for _, tok := range toks {
292 if prev != tok {
Shinichiro Hamajia1358912015-04-11 12:16:21 +0900293 sw.WriteString(tok)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900294 prev = tok
295 }
296 }
297}
298
299type funcWord struct{ fclosure }
300
301func (f *funcWord) Arity() int { return 2 }
302func (f *funcWord) Eval(w io.Writer, ev *Evaluator) {
303 assertArity("word", 2, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900304 abuf := newBuf()
305 fargs := ev.args(abuf, f.args[1:]...)
306 v := string(trimSpaceBytes(fargs[0]))
307 index, ok := numericValueForFunc(v)
308 if !ok {
309 Error(ev.filename, ev.lineno, `*** non-numeric first argument to "word" function: %q.`, v)
310 }
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900311 if index == 0 {
312 Error(ev.filename, ev.lineno, `*** first argument to "word" function must be greater than 0.`)
313 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900314 ws := newWordScanner(fargs[1])
315 for ws.Scan() {
316 index--
317 if index == 0 {
318 w.Write(ws.Bytes())
319 break
320 }
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900321 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900322 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900323}
324
325type funcWordlist struct{ fclosure }
326
327func (f *funcWordlist) Arity() int { return 3 }
328func (f *funcWordlist) Eval(w io.Writer, ev *Evaluator) {
329 assertArity("wordlist", 3, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900330 abuf := newBuf()
331 fargs := ev.args(abuf, f.args[1:]...)
332 v := string(trimSpaceBytes(fargs[0]))
333 si, ok := numericValueForFunc(v)
334 if !ok {
335 Error(ev.filename, ev.lineno, `*** non-numeric first argument to "wordlist" function: %q.`, v)
336 }
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900337 if si == 0 {
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900338 Error(ev.filename, ev.lineno, `*** invalid first argument to "wordlist" function: %s`, f.args[1])
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900339 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900340 v = string(trimSpaceBytes(fargs[1]))
341 ei, ok := numericValueForFunc(v)
342 if !ok {
343 Error(ev.filename, ev.lineno, `*** non-numeric second argument to "wordlist" function: %q.`, v)
344 }
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900345
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900346 ws := newWordScanner(fargs[2])
347 i := 0
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900348 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900349 for ws.Scan() {
350 i++
351 if si <= i && i <= ei {
352 sw.Write(ws.Bytes())
353 }
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900354 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900355 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900356}
357
358type funcWords struct{ fclosure }
359
360func (f *funcWords) Arity() int { return 1 }
361func (f *funcWords) Eval(w io.Writer, ev *Evaluator) {
362 assertArity("words", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900363 abuf := newBuf()
364 f.args[1].Eval(abuf, ev)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900365 ws := newWordScanner(abuf.Bytes())
366 n := 0
367 for ws.Scan() {
368 n++
369 }
370 w.Write([]byte(strconv.Itoa(n)))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900371 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900372}
373
374type funcFirstword struct{ fclosure }
375
376func (f *funcFirstword) Arity() int { return 1 }
377func (f *funcFirstword) Eval(w io.Writer, ev *Evaluator) {
378 assertArity("firstword", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900379 abuf := newBuf()
380 f.args[1].Eval(abuf, ev)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900381 ws := newWordScanner(abuf.Bytes())
382 if ws.Scan() {
383 w.Write(ws.Bytes())
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900384 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900385 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900386}
387
388type funcLastword struct{ fclosure }
389
390func (f *funcLastword) Arity() int { return 1 }
391func (f *funcLastword) Eval(w io.Writer, ev *Evaluator) {
392 assertArity("lastword", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900393 abuf := newBuf()
394 f.args[1].Eval(abuf, ev)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900395 ws := newWordScanner(abuf.Bytes())
396 var lw []byte
397 for ws.Scan() {
398 lw = ws.Bytes()
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900399 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900400 if lw != nil {
401 w.Write(lw)
402 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900403 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900404}
405
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900406// https://www.gnu.org/software/make/manual/html_node/File-Name-Functions.html#File-Name-Functions
407
408type funcJoin struct{ fclosure }
409
410func (f *funcJoin) Arity() int { return 2 }
411func (f *funcJoin) Eval(w io.Writer, ev *Evaluator) {
412 assertArity("join", 2, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900413 abuf := newBuf()
414 fargs := ev.args(abuf, f.args[1:]...)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900415 ws1 := newWordScanner(fargs[0])
416 ws2 := newWordScanner(fargs[1])
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900417 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900418 for {
419 if w1, w2 := ws1.Scan(), ws2.Scan(); !w1 && !w2 {
420 break
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900421 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900422 sw.Write(ws1.Bytes())
423 // Use |w| not to append extra ' '.
424 w.Write(ws2.Bytes())
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900425 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900426 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900427}
428
429type funcWildcard struct{ fclosure }
430
431func (f *funcWildcard) Arity() int { return 1 }
432func (f *funcWildcard) Eval(w io.Writer, ev *Evaluator) {
433 assertArity("wildcard", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900434 abuf := newBuf()
435 f.args[1].Eval(abuf, ev)
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +0900436 if ev.avoidIO {
437 ev.hasIO = true
Shinichiro Hamaji4c68b4c2015-06-03 22:46:03 +0900438 w.Write([]byte("$(/bin/ls -d "))
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +0900439 w.Write(abuf.Bytes())
440 w.Write([]byte(" 2> /dev/null)"))
441 return
442 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900443 ws := newWordScanner(abuf.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900444 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900445 for ws.Scan() {
Shinichiro Hamajiba6b84d2015-06-03 18:46:13 +0900446 pat := string(ws.Bytes())
447 if strings.Contains(pat, "..") {
448 // For some reason, go's Glob normalizes
449 // foo/../bar to bar. We ask shell to expand
450 // a glob to avoid this.
Shinichiro Hamaji4c68b4c2015-06-03 22:46:03 +0900451 cmdline := []string{"/bin/sh", "-c", "/bin/ls -d " + pat}
Shinichiro Hamajiba6b84d2015-06-03 18:46:13 +0900452 cmd := exec.Cmd{
453 Path: cmdline[0],
454 Args: cmdline,
455 }
456 // Ignore errors.
457 out, _ := cmd.Output()
Shinichiro Hamaji73957cf2015-06-05 09:19:37 +0900458 if len(trimSpaceBytes(out)) > 0 {
459 sw.Write(formatCommandOutput(out))
460 }
Shinichiro Hamajiba6b84d2015-06-03 18:46:13 +0900461 } else {
462 files, err := filepath.Glob(string(ws.Bytes()))
463 if err != nil {
464 panic(err)
465 }
466 for _, file := range files {
467 sw.WriteString(file)
468 }
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900469 }
470 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900471 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900472}
473
474type funcDir struct{ fclosure }
475
476func (f *funcDir) Arity() int { return 1 }
477func (f *funcDir) Eval(w io.Writer, ev *Evaluator) {
478 assertArity("dir", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900479 abuf := newBuf()
480 f.args[1].Eval(abuf, ev)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900481 ws := newWordScanner(abuf.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900482 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900483 for ws.Scan() {
484 name := string(ws.Bytes())
Shinichiro Hamaji37626b62015-04-21 16:59:23 +0900485 if name == "/" {
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900486 sw.WriteString(name)
487 continue
Shinichiro Hamaji37626b62015-04-21 16:59:23 +0900488 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900489 sw.WriteString(filepath.Dir(string(name)) + string(filepath.Separator))
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900490 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900491 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900492}
493
494type funcNotdir struct{ fclosure }
495
496func (f *funcNotdir) Arity() int { return 1 }
497func (f *funcNotdir) Eval(w io.Writer, ev *Evaluator) {
498 assertArity("notdir", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900499 abuf := newBuf()
500 f.args[1].Eval(abuf, ev)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900501 ws := newWordScanner(abuf.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900502 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900503 for ws.Scan() {
504 name := string(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900505 if name == string(filepath.Separator) {
506 sw.Write([]byte{})
507 continue
508 }
Shinichiro Hamajia1358912015-04-11 12:16:21 +0900509 sw.WriteString(filepath.Base(name))
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900510 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900511 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900512}
513
514type funcSuffix struct{ fclosure }
515
516func (f *funcSuffix) Arity() int { return 1 }
517func (f *funcSuffix) Eval(w io.Writer, ev *Evaluator) {
518 assertArity("suffix", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900519 abuf := newBuf()
520 f.args[1].Eval(abuf, ev)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900521 ws := newWordScanner(abuf.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900522 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900523 for ws.Scan() {
524 tok := string(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900525 e := filepath.Ext(tok)
526 if len(e) > 0 {
Shinichiro Hamajia1358912015-04-11 12:16:21 +0900527 sw.WriteString(e)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900528 }
529 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900530 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900531}
532
533type funcBasename struct{ fclosure }
534
535func (f *funcBasename) Arity() int { return 1 }
536func (f *funcBasename) Eval(w io.Writer, ev *Evaluator) {
537 assertArity("basename", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900538 abuf := newBuf()
539 f.args[1].Eval(abuf, ev)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900540 ws := newWordScanner(abuf.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900541 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900542 for ws.Scan() {
543 tok := string(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900544 e := stripExt(tok)
Shinichiro Hamajia1358912015-04-11 12:16:21 +0900545 sw.WriteString(e)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900546 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900547 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900548}
549
550type funcAddsuffix struct{ fclosure }
551
552func (f *funcAddsuffix) Arity() int { return 2 }
553func (f *funcAddsuffix) Eval(w io.Writer, ev *Evaluator) {
554 assertArity("addsuffix", 2, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900555 abuf := newBuf()
556 fargs := ev.args(abuf, f.args[1:]...)
557 suf := fargs[0]
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900558 ws := newWordScanner(fargs[1])
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900559 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900560 for ws.Scan() {
561 sw.Write(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900562 // Use |w| not to append extra ' '.
563 w.Write(suf)
564 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900565 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900566}
567
568type funcAddprefix struct{ fclosure }
569
570func (f *funcAddprefix) Arity() int { return 2 }
571func (f *funcAddprefix) Eval(w io.Writer, ev *Evaluator) {
572 assertArity("addprefix", 2, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900573 abuf := newBuf()
574 fargs := ev.args(abuf, f.args[1:]...)
575 pre := fargs[0]
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900576 ws := newWordScanner(fargs[1])
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900577 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900578 for ws.Scan() {
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900579 sw.Write(pre)
580 // Use |w| not to append extra ' '.
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900581 w.Write(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900582 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900583 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900584}
585
586type funcRealpath struct{ fclosure }
587
588func (f *funcRealpath) Arity() int { return 1 }
589func (f *funcRealpath) Eval(w io.Writer, ev *Evaluator) {
590 assertArity("realpath", 1, len(f.args))
Shinichiro Hamajib41fd502015-04-29 03:34:07 +0900591 if ev.avoidIO {
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +0900592 w.Write([]byte("KATI_TODO(realpath)"))
Shinichiro Hamajib41fd502015-04-29 03:34:07 +0900593 ev.hasIO = true
594 return
595 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900596 abuf := newBuf()
597 f.args[1].Eval(abuf, ev)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900598 ws := newWordScanner(abuf.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900599 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900600 for ws.Scan() {
601 name := string(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900602 name, err := filepath.Abs(name)
603 if err != nil {
604 Log("abs: %v", err)
605 continue
606 }
607 name, err = filepath.EvalSymlinks(name)
608 if err != nil {
609 Log("realpath: %v", err)
610 continue
611 }
Shinichiro Hamajia1358912015-04-11 12:16:21 +0900612 sw.WriteString(name)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900613 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900614 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900615}
616
617type funcAbspath struct{ fclosure }
618
619func (f *funcAbspath) Arity() int { return 1 }
620func (f *funcAbspath) Eval(w io.Writer, ev *Evaluator) {
621 assertArity("abspath", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900622 abuf := newBuf()
623 f.args[1].Eval(abuf, ev)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900624 ws := newWordScanner(abuf.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900625 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900626 for ws.Scan() {
627 name := string(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900628 name, err := filepath.Abs(name)
629 if err != nil {
630 Log("abs: %v", err)
631 continue
632 }
Shinichiro Hamajia1358912015-04-11 12:16:21 +0900633 sw.WriteString(name)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900634 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900635 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900636}
637
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900638// http://www.gnu.org/software/make/manual/make.html#Conditional-Functions
639type funcIf struct{ fclosure }
640
641func (f *funcIf) Arity() int { return 3 }
642func (f *funcIf) Eval(w io.Writer, ev *Evaluator) {
643 assertArity("if", 2, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900644 abuf := newBuf()
645 f.args[1].Eval(abuf, ev)
646 if len(abuf.Bytes()) != 0 {
647 freeBuf(abuf)
Fumitoshi Ukaie27a25d2015-04-18 00:31:01 +0900648 f.args[2].Eval(w, ev)
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900649 return
650 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900651 freeBuf(abuf)
Fumitoshi Ukaie27a25d2015-04-18 00:31:01 +0900652 if len(f.args) > 3 {
653 f.args[3].Eval(w, ev)
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900654 }
655}
656
657type funcAnd struct{ fclosure }
658
659func (f *funcAnd) Arity() int { return 0 }
660func (f *funcAnd) Eval(w io.Writer, ev *Evaluator) {
661 assertArity("and", 0, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900662 abuf := newBuf()
Shinichiro Hamaji2216dd62015-04-11 13:44:39 +0900663 var cond []byte
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900664 for _, arg := range f.args[1:] {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900665 abuf.Reset()
666 arg.Eval(abuf, ev)
667 cond = abuf.Bytes()
Shinichiro Hamaji2216dd62015-04-11 13:44:39 +0900668 if len(cond) == 0 {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900669 freeBuf(abuf)
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900670 return
671 }
672 }
Shinichiro Hamaji2216dd62015-04-11 13:44:39 +0900673 w.Write(cond)
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900674 freeBuf(abuf)
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900675}
676
677type funcOr struct{ fclosure }
678
679func (f *funcOr) Arity() int { return 0 }
680func (f *funcOr) Eval(w io.Writer, ev *Evaluator) {
681 assertArity("or", 0, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900682 abuf := newBuf()
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900683 for _, arg := range f.args[1:] {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900684 abuf.Reset()
685 arg.Eval(abuf, ev)
686 cond := abuf.Bytes()
Shinichiro Hamaji2216dd62015-04-11 13:44:39 +0900687 if len(cond) != 0 {
688 w.Write(cond)
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900689 freeBuf(abuf)
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900690 return
691 }
692 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900693 freeBuf(abuf)
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900694}
695
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900696// http://www.gnu.org/software/make/manual/make.html#Shell-Function
697type funcShell struct{ fclosure }
698
Fumitoshi Ukai586b02a2015-05-08 00:23:10 +0900699var shellFuncTime time.Duration
700
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900701func (f *funcShell) Arity() int { return 1 }
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900702
Shinichiro Hamajic0095e32015-05-27 18:49:06 +0900703// A hack for Android build. We need to evaluate things like $((3+4))
704// when we emit ninja file, because the result of such expressions
705// will be passed to other make functions.
706// TODO: Maybe we should modify Android's Makefile and remove this
707// workaround. It would be also nice if we can detect things like
708// this.
709func hasNoIoInShellScript(s []byte) bool {
710 if len(s) == 0 {
711 return true
712 }
713 if !bytes.HasPrefix(s, []byte("echo $((")) || s[len(s)-1] != ')' {
714 return false
715 }
Shinichiro Hamaji80017a02015-05-27 18:56:38 +0900716 Log("has no IO - evaluate now: %s", s)
Shinichiro Hamajic0095e32015-05-27 18:49:06 +0900717 return true
718}
719
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900720func (f *funcShell) Eval(w io.Writer, ev *Evaluator) {
721 assertArity("shell", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900722 abuf := newBuf()
723 f.args[1].Eval(abuf, ev)
Shinichiro Hamajic0095e32015-05-27 18:49:06 +0900724 if ev.avoidIO && !hasNoIoInShellScript(abuf.Bytes()) {
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +0900725 ev.hasIO = true
726 w.Write([]byte("$("))
727 w.Write(abuf.Bytes())
728 w.Write([]byte{')'})
729 return
730 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900731 arg := abuf.String()
732 freeBuf(abuf)
Shinichiro Hamaji89551c92015-04-11 19:33:03 +0900733 shellVar := ev.LookupVar("SHELL")
734 // TODO: Should be Eval, not String.
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900735 cmdline := []string{shellVar.String(), "-c", arg}
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900736 cmd := exec.Cmd{
737 Path: cmdline[0],
738 Args: cmdline,
739 Stderr: os.Stderr,
740 }
Fumitoshi Ukai586b02a2015-05-08 00:23:10 +0900741 t := time.Now()
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900742 out, err := cmd.Output()
Fumitoshi Ukai586b02a2015-05-08 00:23:10 +0900743 shellFuncTime += time.Now().Sub(t)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900744 if err != nil {
745 Log("$(shell %q) failed: %q", arg, err)
746 }
747
Shinichiro Hamajiba6b84d2015-06-03 18:46:13 +0900748 w.Write(formatCommandOutput(out))
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900749}
750
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +0900751// https://www.gnu.org/software/make/manual/html_node/Call-Function.html#Call-Function
752type funcCall struct{ fclosure }
753
754func (f *funcCall) Arity() int { return 0 }
755
756func (f *funcCall) Eval(w io.Writer, ev *Evaluator) {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900757 abuf := newBuf()
758 fargs := ev.args(abuf, f.args[1:]...)
759 variable := fargs[0]
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900760 Log("call %q variable %q", f.args[1], variable)
761 v := ev.LookupVar(string(variable))
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +0900762 // Evalualte all arguments first before we modify the table.
Shinichiro Hamaji39728f12015-04-11 20:12:23 +0900763 var args []tmpval
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900764 // $0 is variable.
765 args = append(args, tmpval(variable))
766 // TODO(ukai): If variable is the name of a built-in function,
767 // the built-in function is always invoked (even if a make variable
768 // by that name also exists).
769
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900770 for i, arg := range fargs[1:] {
771 // f.args[2]=>args[1] will be $1.
772 args = append(args, tmpval(arg))
773 Log("call $%d: %q=>%q", i+1, arg, fargs[i+1])
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +0900774 }
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900775 oldParams := ev.paramVars
776 ev.paramVars = args
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +0900777
Fumitoshi Ukai9b10ecf2015-04-15 17:45:50 +0900778 var restores []func()
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +0900779 for i, arg := range args {
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900780 name := fmt.Sprintf("%d", i)
Fumitoshi Ukai9b10ecf2015-04-15 17:45:50 +0900781 restores = append(restores, ev.outVars.save(name))
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900782 ev.outVars.Assign(name, SimpleVar{
783 value: arg,
784 origin: "automatic", // ??
785 })
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +0900786 }
787
788 var buf bytes.Buffer
Fumitoshi Ukaie27a25d2015-04-18 00:31:01 +0900789 if katiLogFlag {
790 w = io.MultiWriter(w, &buf)
791 }
792 v.Eval(w, ev)
Fumitoshi Ukai9b10ecf2015-04-15 17:45:50 +0900793 for _, restore := range restores {
794 restore()
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +0900795 }
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900796 ev.paramVars = oldParams
797 Log("call %q variable %q return %q", f.args[1], variable, buf.Bytes())
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900798 freeBuf(abuf)
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +0900799}
800
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +0900801// http://www.gnu.org/software/make/manual/make.html#Value-Function
802type funcValue struct{ fclosure }
803
804func (f *funcValue) Arity() int { return 1 }
805func (f *funcValue) Eval(w io.Writer, ev *Evaluator) {
806 assertArity("value", 1, len(f.args))
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900807 v := ev.LookupVar(f.args[1].String())
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +0900808 w.Write([]byte(v.String()))
809}
810
811// http://www.gnu.org/software/make/manual/make.html#Eval-Function
812type funcEval struct{ fclosure }
813
814func (f *funcEval) Arity() int { return 1 }
815func (f *funcEval) Eval(w io.Writer, ev *Evaluator) {
816 assertArity("eval", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900817 abuf := newBuf()
818 f.args[1].Eval(abuf, ev)
819 s := abuf.Bytes()
820 Log("eval %q at %s:%d", s, ev.filename, ev.lineno)
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +0900821 mk, err := ParseMakefileBytes(s, ev.filename, ev.lineno)
822 if err != nil {
823 panic(err)
824 }
825
826 for _, stmt := range mk.stmts {
827 ev.eval(stmt)
828 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900829 freeBuf(abuf)
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +0900830}
831
Fumitoshi Ukai9f6b6352015-04-16 16:25:09 +0900832func (f *funcEval) Compact() Value {
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900833 if len(f.args)-1 < 1 {
834 return f
835 }
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900836 switch arg := f.args[1].(type) {
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900837 case literal, tmpval:
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900838 case Expr:
839 if len(arg) == 1 {
840 return f
841 }
842 switch prefix := arg[0].(type) {
843 case literal, tmpval:
844 lhs, op, rhsprefix, ok := parseAssignLiteral(prefix.String())
845 if ok {
846 // $(eval foo = $(bar))
847 var rhs Expr
848 if rhsprefix != literal("") {
849 rhs = append(rhs, rhsprefix)
850 }
851 rhs = append(rhs, arg[1:]...)
852 Log("eval assign %#v => lhs:%q op:%q rhs:%#v", f, lhs, op, rhs)
853 return &funcEvalAssign{
854 lhs: lhs,
855 op: op,
856 rhs: compactExpr(rhs),
857 }
858 }
859 }
860 // TODO(ukai): eval -> varassign. e.g $(eval $(foo) := $(x)).
Fumitoshi Ukai769157a2015-06-02 15:18:53 +0900861 return f
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900862 default:
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900863 return f
864 }
865 arg := f.args[1].String()
866 arg = stripComment(arg)
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900867 if arg == "" || strings.TrimSpace(arg) == "" {
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900868 return &funcNop{expr: f.String()}
869 }
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900870 f.args[1] = literal(arg)
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900871 lhs, op, rhs, ok := parseAssignLiteral(f.args[1].String())
872 if ok {
Fumitoshi Ukai150c8612015-04-16 15:35:44 +0900873 return &funcEvalAssign{
874 lhs: lhs,
875 op: op,
876 rhs: rhs,
877 }
878 }
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900879 return f
880}
881
882func stripComment(arg string) string {
883 for {
884 i := strings.Index(arg, "#")
885 if i < 0 {
886 return arg
887 }
888 eol := strings.Index(arg[i:], "\n")
889 if eol < 0 {
890 return arg[:i]
891 }
892 arg = arg[:i] + arg[eol+1:]
893 }
894}
895
896type funcNop struct{ expr string }
897
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900898func (f *funcNop) String() string { return f.expr }
899func (f *funcNop) Eval(io.Writer, *Evaluator) {}
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900900func (f *funcNop) Serialize() SerializableVar {
901 return SerializableVar{
902 Type: "funcNop",
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900903 V: f.expr,
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900904 }
905}
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900906func (f *funcNop) Dump(w io.Writer) {
907 dumpByte(w, VALUE_TYPE_NOP)
908}
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900909
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900910func parseAssignLiteral(s string) (lhs, op string, rhs Value, ok bool) {
911 eq := strings.Index(s, "=")
912 if eq < 0 {
913 return "", "", nil, false
914 }
915 // TODO(ukai): factor out parse assign?
916 lhs = s[:eq]
917 op = s[eq : eq+1]
918 if eq >= 1 && (s[eq-1] == ':' || s[eq-1] == '+' || s[eq-1] == '?') {
919 lhs = s[:eq-1]
920 op = s[eq-1 : eq+1]
921 }
922 lhs = strings.TrimSpace(lhs)
923 if strings.IndexAny(lhs, ":$") >= 0 {
924 // target specific var, or need eval.
925 return "", "", nil, false
926 }
927 r := strings.TrimLeft(s[eq+1:], " \t")
928 rhs = literal(r)
929 return lhs, op, rhs, true
930}
931
Fumitoshi Ukai150c8612015-04-16 15:35:44 +0900932type funcEvalAssign struct {
933 lhs string
934 op string
935 rhs Value
936}
937
Fumitoshi Ukai150c8612015-04-16 15:35:44 +0900938func (f *funcEvalAssign) String() string {
939 return fmt.Sprintf("$(eval %s %s %s)", f.lhs, f.op, f.rhs)
940}
941
942func (f *funcEvalAssign) Eval(w io.Writer, ev *Evaluator) {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900943 var abuf bytes.Buffer
944 f.rhs.Eval(&abuf, ev)
945 rhs := trimLeftSpaceBytes(abuf.Bytes())
Fumitoshi Ukai150c8612015-04-16 15:35:44 +0900946 var rvalue Var
947 switch f.op {
948 case ":=":
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900949 // TODO(ukai): compute parsed expr in Compact when f.rhs is
950 // literal? e.g. literal("$(foo)") => varref{literal("foo")}.
Fumitoshi Ukaifa5e9222015-04-17 11:45:20 +0900951 expr, _, err := parseExpr(rhs, nil)
952 if err != nil {
953 panic(fmt.Sprintf("eval assign error: %q: %v", f.String(), err))
954 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900955 abuf.Reset()
956 expr.Eval(&abuf, ev)
957 rvalue = SimpleVar{value: tmpval(abuf.Bytes()), origin: "file"}
Fumitoshi Ukai150c8612015-04-16 15:35:44 +0900958 case "=":
959 rvalue = RecursiveVar{expr: tmpval(rhs), origin: "file"}
960 case "+=":
961 prev := ev.LookupVar(f.lhs)
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900962 if prev.IsDefined() {
Fumitoshi Ukai150c8612015-04-16 15:35:44 +0900963 rvalue = prev.Append(ev, string(rhs))
964 } else {
965 rvalue = RecursiveVar{expr: tmpval(rhs), origin: "file"}
966 }
967 case "?=":
968 prev := ev.LookupVar(f.lhs)
969 if prev.IsDefined() {
970 return
971 }
972 rvalue = RecursiveVar{expr: tmpval(rhs), origin: "file"}
973 }
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900974 Log("Eval ASSIGN: %s=%q (flavor:%q)", f.lhs, rvalue, rvalue.Flavor())
Fumitoshi Ukai150c8612015-04-16 15:35:44 +0900975 ev.outVars.Assign(f.lhs, rvalue)
976}
977
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900978func (f *funcEvalAssign) Serialize() SerializableVar {
979 return SerializableVar{
980 Type: "funcEvalAssign",
981 Children: []SerializableVar{
982 SerializableVar{V: f.lhs},
983 SerializableVar{V: f.op},
984 f.rhs.Serialize(),
985 },
986 }
987}
988
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900989func (f *funcEvalAssign) Dump(w io.Writer) {
990 dumpByte(w, VALUE_TYPE_ASSIGN)
991 dumpString(w, f.lhs)
992 dumpString(w, f.op)
993 f.rhs.Dump(w)
994}
995
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +0900996// http://www.gnu.org/software/make/manual/make.html#Origin-Function
997type funcOrigin struct{ fclosure }
998
999func (f *funcOrigin) Arity() int { return 1 }
1000func (f *funcOrigin) Eval(w io.Writer, ev *Evaluator) {
1001 assertArity("origin", 1, len(f.args))
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +09001002 v := ev.LookupVar(f.args[1].String())
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001003 w.Write([]byte(v.Origin()))
1004}
1005
1006// https://www.gnu.org/software/make/manual/html_node/Flavor-Function.html#Flavor-Function
1007type funcFlavor struct{ fclosure }
1008
1009func (f *funcFlavor) Arity() int { return 1 }
1010func (f *funcFlavor) Eval(w io.Writer, ev *Evaluator) {
1011 assertArity("flavor", 1, len(f.args))
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +09001012 v := ev.LookupVar(f.args[1].String())
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001013 w.Write([]byte(v.Flavor()))
1014}
1015
1016// http://www.gnu.org/software/make/manual/make.html#Make-Control-Functions
1017type funcInfo struct{ fclosure }
1018
1019func (f *funcInfo) Arity() int { return 1 }
1020func (f *funcInfo) Eval(w io.Writer, ev *Evaluator) {
1021 assertArity("info", 1, len(f.args))
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001022 if ev.avoidIO {
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +09001023 w.Write([]byte("KATI_TODO(info)"))
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001024 ev.hasIO = true
1025 return
1026 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001027 abuf := newBuf()
1028 f.args[1].Eval(abuf, ev)
1029 fmt.Printf("%s\n", abuf.String())
1030 freeBuf(abuf)
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001031}
1032
1033type funcWarning struct{ fclosure }
1034
1035func (f *funcWarning) Arity() int { return 1 }
1036func (f *funcWarning) Eval(w io.Writer, ev *Evaluator) {
1037 assertArity("warning", 1, len(f.args))
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001038 if ev.avoidIO {
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +09001039 w.Write([]byte("KATI_TODO(warning)"))
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001040 ev.hasIO = true
1041 return
1042 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001043 abuf := newBuf()
1044 f.args[1].Eval(abuf, ev)
1045 fmt.Printf("%s:%d: %s\n", ev.filename, ev.lineno, abuf.String())
1046 freeBuf(abuf)
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001047}
1048
1049type funcError struct{ fclosure }
1050
1051func (f *funcError) Arity() int { return 1 }
1052func (f *funcError) Eval(w io.Writer, ev *Evaluator) {
1053 assertArity("error", 1, len(f.args))
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001054 if ev.avoidIO {
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +09001055 w.Write([]byte("KATI_TODO(error)"))
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001056 ev.hasIO = true
1057 return
1058 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001059 abuf := newBuf()
1060 f.args[1].Eval(abuf, ev)
1061 Error(ev.filename, ev.lineno, "*** %s.", abuf.String())
1062 freeBuf(abuf)
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001063}
1064
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001065// http://www.gnu.org/software/make/manual/make.html#Foreach-Function
1066type funcForeach struct{ fclosure }
1067
1068func (f *funcForeach) Arity() int { return 3 }
1069
1070func (f *funcForeach) Eval(w io.Writer, ev *Evaluator) {
1071 assertArity("foreach", 3, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001072 abuf := newBuf()
1073 fargs := ev.args(abuf, f.args[1], f.args[2])
1074 varname := string(fargs[0])
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +09001075 ws := newWordScanner(fargs[1])
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +09001076 text := f.args[3]
Fumitoshi Ukai9b10ecf2015-04-15 17:45:50 +09001077 restore := ev.outVars.save(varname)
1078 defer restore()
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001079 space := false
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +09001080 for ws.Scan() {
1081 word := ws.Bytes()
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001082 ev.outVars.Assign(varname,
1083 SimpleVar{
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001084 value: tmpval(word),
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001085 origin: "automatic",
1086 })
1087 if space {
1088 w.Write([]byte{' '})
1089 }
Fumitoshi Ukaie27a25d2015-04-18 00:31:01 +09001090 text.Eval(w, ev)
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001091 space = true
1092 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001093 freeBuf(abuf)
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001094}