blob: 36c1433c5e3d62ba15fe51d27983f99831b68bc0 [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)
202 w.Write(trimSpaceBytes(abuf.Bytes()))
203 freeBuf(abuf)
Shinichiro Hamaji98e910d2015-04-11 10:38:44 +0900204}
205
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900206type funcFindstring struct{ fclosure }
207
208func (f *funcFindstring) Arity() int { return 2 }
209func (f *funcFindstring) Eval(w io.Writer, ev *Evaluator) {
210 assertArity("findstring", 2, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900211 abuf := newBuf()
212 fargs := ev.args(abuf, f.args[1:]...)
213 find := fargs[0]
214 text := fargs[1]
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900215 if bytes.Index(text, find) >= 0 {
216 w.Write(find)
217 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900218 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900219}
220
221type funcFilter struct{ fclosure }
222
223func (f *funcFilter) Arity() int { return 2 }
224func (f *funcFilter) Eval(w io.Writer, ev *Evaluator) {
225 assertArity("filter", 2, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900226 abuf := newBuf()
227 fargs := ev.args(abuf, f.args[1:]...)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900228 var patterns [][]byte
229 ws := newWordScanner(fargs[0])
230 for ws.Scan() {
231 patterns = append(patterns, ws.Bytes())
232 }
233 ws = newWordScanner(fargs[1])
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900234 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900235 for ws.Scan() {
236 text := ws.Bytes()
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900237 for _, pat := range patterns {
238 if matchPatternBytes(pat, text) {
239 sw.Write(text)
240 }
241 }
242 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900243 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900244}
245
246type funcFilterOut struct{ fclosure }
247
248func (f *funcFilterOut) Arity() int { return 2 }
249func (f *funcFilterOut) Eval(w io.Writer, ev *Evaluator) {
250 assertArity("filter-out", 2, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900251 abuf := newBuf()
252 fargs := ev.args(abuf, f.args[1:]...)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900253 var patterns [][]byte
254 ws := newWordScanner(fargs[0])
255 for ws.Scan() {
256 patterns = append(patterns, ws.Bytes())
257 }
258 ws = newWordScanner(fargs[1])
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900259 sw := ssvWriter{w: w}
260Loop:
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900261 for ws.Scan() {
262 text := ws.Bytes()
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900263 for _, pat := range patterns {
264 if matchPatternBytes(pat, text) {
265 continue Loop
266 }
267 }
268 sw.Write(text)
269 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900270 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900271}
272
273type funcSort struct{ fclosure }
274
275func (f *funcSort) Arity() int { return 1 }
276func (f *funcSort) Eval(w io.Writer, ev *Evaluator) {
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900277 assertArity("sort", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900278 abuf := newBuf()
279 f.args[1].Eval(abuf, ev)
280 toks := splitSpaces(abuf.String())
281 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900282 sort.Strings(toks)
283
284 // Remove duplicate words.
285 var prev string
286 sw := ssvWriter{w: w}
287 for _, tok := range toks {
288 if prev != tok {
Shinichiro Hamajia1358912015-04-11 12:16:21 +0900289 sw.WriteString(tok)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900290 prev = tok
291 }
292 }
293}
294
295type funcWord struct{ fclosure }
296
297func (f *funcWord) Arity() int { return 2 }
298func (f *funcWord) Eval(w io.Writer, ev *Evaluator) {
299 assertArity("word", 2, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900300 abuf := newBuf()
301 fargs := ev.args(abuf, f.args[1:]...)
302 v := string(trimSpaceBytes(fargs[0]))
303 index, ok := numericValueForFunc(v)
304 if !ok {
305 Error(ev.filename, ev.lineno, `*** non-numeric first argument to "word" function: %q.`, v)
306 }
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900307 if index == 0 {
308 Error(ev.filename, ev.lineno, `*** first argument to "word" function must be greater than 0.`)
309 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900310 ws := newWordScanner(fargs[1])
311 for ws.Scan() {
312 index--
313 if index == 0 {
314 w.Write(ws.Bytes())
315 break
316 }
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900317 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900318 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900319}
320
321type funcWordlist struct{ fclosure }
322
323func (f *funcWordlist) Arity() int { return 3 }
324func (f *funcWordlist) Eval(w io.Writer, ev *Evaluator) {
325 assertArity("wordlist", 3, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900326 abuf := newBuf()
327 fargs := ev.args(abuf, f.args[1:]...)
328 v := string(trimSpaceBytes(fargs[0]))
329 si, ok := numericValueForFunc(v)
330 if !ok {
331 Error(ev.filename, ev.lineno, `*** non-numeric first argument to "wordlist" function: %q.`, v)
332 }
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900333 if si == 0 {
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900334 Error(ev.filename, ev.lineno, `*** invalid first argument to "wordlist" function: %s`, f.args[1])
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900335 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900336 v = string(trimSpaceBytes(fargs[1]))
337 ei, ok := numericValueForFunc(v)
338 if !ok {
339 Error(ev.filename, ev.lineno, `*** non-numeric second argument to "wordlist" function: %q.`, v)
340 }
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900341
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900342 ws := newWordScanner(fargs[2])
343 i := 0
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900344 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900345 for ws.Scan() {
346 i++
347 if si <= i && i <= ei {
348 sw.Write(ws.Bytes())
349 }
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900350 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900351 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900352}
353
354type funcWords struct{ fclosure }
355
356func (f *funcWords) Arity() int { return 1 }
357func (f *funcWords) Eval(w io.Writer, ev *Evaluator) {
358 assertArity("words", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900359 abuf := newBuf()
360 f.args[1].Eval(abuf, ev)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900361 ws := newWordScanner(abuf.Bytes())
362 n := 0
363 for ws.Scan() {
364 n++
365 }
366 w.Write([]byte(strconv.Itoa(n)))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900367 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900368}
369
370type funcFirstword struct{ fclosure }
371
372func (f *funcFirstword) Arity() int { return 1 }
373func (f *funcFirstword) Eval(w io.Writer, ev *Evaluator) {
374 assertArity("firstword", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900375 abuf := newBuf()
376 f.args[1].Eval(abuf, ev)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900377 ws := newWordScanner(abuf.Bytes())
378 if ws.Scan() {
379 w.Write(ws.Bytes())
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900380 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900381 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900382}
383
384type funcLastword struct{ fclosure }
385
386func (f *funcLastword) Arity() int { return 1 }
387func (f *funcLastword) Eval(w io.Writer, ev *Evaluator) {
388 assertArity("lastword", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900389 abuf := newBuf()
390 f.args[1].Eval(abuf, ev)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900391 ws := newWordScanner(abuf.Bytes())
392 var lw []byte
393 for ws.Scan() {
394 lw = ws.Bytes()
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900395 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900396 if lw != nil {
397 w.Write(lw)
398 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900399 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900400}
401
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900402// https://www.gnu.org/software/make/manual/html_node/File-Name-Functions.html#File-Name-Functions
403
404type funcJoin struct{ fclosure }
405
406func (f *funcJoin) Arity() int { return 2 }
407func (f *funcJoin) Eval(w io.Writer, ev *Evaluator) {
408 assertArity("join", 2, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900409 abuf := newBuf()
410 fargs := ev.args(abuf, f.args[1:]...)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900411 ws1 := newWordScanner(fargs[0])
412 ws2 := newWordScanner(fargs[1])
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900413 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900414 for {
415 if w1, w2 := ws1.Scan(), ws2.Scan(); !w1 && !w2 {
416 break
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900417 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900418 sw.Write(ws1.Bytes())
419 // Use |w| not to append extra ' '.
420 w.Write(ws2.Bytes())
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900421 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900422 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900423}
424
425type funcWildcard struct{ fclosure }
426
427func (f *funcWildcard) Arity() int { return 1 }
428func (f *funcWildcard) Eval(w io.Writer, ev *Evaluator) {
429 assertArity("wildcard", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900430 abuf := newBuf()
431 f.args[1].Eval(abuf, ev)
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +0900432 if ev.avoidIO {
433 ev.hasIO = true
Shinichiro Hamaji4c68b4c2015-06-03 22:46:03 +0900434 w.Write([]byte("$(/bin/ls -d "))
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +0900435 w.Write(abuf.Bytes())
436 w.Write([]byte(" 2> /dev/null)"))
437 return
438 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900439 ws := newWordScanner(abuf.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900440 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900441 for ws.Scan() {
Shinichiro Hamajiba6b84d2015-06-03 18:46:13 +0900442 pat := string(ws.Bytes())
443 if strings.Contains(pat, "..") {
444 // For some reason, go's Glob normalizes
445 // foo/../bar to bar. We ask shell to expand
446 // a glob to avoid this.
Shinichiro Hamaji4c68b4c2015-06-03 22:46:03 +0900447 cmdline := []string{"/bin/sh", "-c", "/bin/ls -d " + pat}
Shinichiro Hamajiba6b84d2015-06-03 18:46:13 +0900448 cmd := exec.Cmd{
449 Path: cmdline[0],
450 Args: cmdline,
451 }
452 // Ignore errors.
453 out, _ := cmd.Output()
Shinichiro Hamaji07a93802015-06-05 09:17:20 +0900454 sw.Write(formatCommandOutput(out))
Shinichiro Hamajiba6b84d2015-06-03 18:46:13 +0900455 } else {
456 files, err := filepath.Glob(string(ws.Bytes()))
457 if err != nil {
458 panic(err)
459 }
460 for _, file := range files {
461 sw.WriteString(file)
462 }
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900463 }
464 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900465 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900466}
467
468type funcDir struct{ fclosure }
469
470func (f *funcDir) Arity() int { return 1 }
471func (f *funcDir) Eval(w io.Writer, ev *Evaluator) {
472 assertArity("dir", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900473 abuf := newBuf()
474 f.args[1].Eval(abuf, ev)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900475 ws := newWordScanner(abuf.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900476 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900477 for ws.Scan() {
478 name := string(ws.Bytes())
Shinichiro Hamaji37626b62015-04-21 16:59:23 +0900479 if name == "/" {
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900480 sw.WriteString(name)
481 continue
Shinichiro Hamaji37626b62015-04-21 16:59:23 +0900482 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900483 sw.WriteString(filepath.Dir(string(name)) + string(filepath.Separator))
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900484 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900485 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900486}
487
488type funcNotdir struct{ fclosure }
489
490func (f *funcNotdir) Arity() int { return 1 }
491func (f *funcNotdir) Eval(w io.Writer, ev *Evaluator) {
492 assertArity("notdir", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900493 abuf := newBuf()
494 f.args[1].Eval(abuf, ev)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900495 ws := newWordScanner(abuf.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900496 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900497 for ws.Scan() {
498 name := string(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900499 if name == string(filepath.Separator) {
500 sw.Write([]byte{})
501 continue
502 }
Shinichiro Hamajia1358912015-04-11 12:16:21 +0900503 sw.WriteString(filepath.Base(name))
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900504 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900505 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900506}
507
508type funcSuffix struct{ fclosure }
509
510func (f *funcSuffix) Arity() int { return 1 }
511func (f *funcSuffix) Eval(w io.Writer, ev *Evaluator) {
512 assertArity("suffix", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900513 abuf := newBuf()
514 f.args[1].Eval(abuf, ev)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900515 ws := newWordScanner(abuf.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900516 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900517 for ws.Scan() {
518 tok := string(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900519 e := filepath.Ext(tok)
520 if len(e) > 0 {
Shinichiro Hamajia1358912015-04-11 12:16:21 +0900521 sw.WriteString(e)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900522 }
523 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900524 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900525}
526
527type funcBasename struct{ fclosure }
528
529func (f *funcBasename) Arity() int { return 1 }
530func (f *funcBasename) Eval(w io.Writer, ev *Evaluator) {
531 assertArity("basename", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900532 abuf := newBuf()
533 f.args[1].Eval(abuf, ev)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900534 ws := newWordScanner(abuf.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900535 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900536 for ws.Scan() {
537 tok := string(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900538 e := stripExt(tok)
Shinichiro Hamajia1358912015-04-11 12:16:21 +0900539 sw.WriteString(e)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900540 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900541 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900542}
543
544type funcAddsuffix struct{ fclosure }
545
546func (f *funcAddsuffix) Arity() int { return 2 }
547func (f *funcAddsuffix) Eval(w io.Writer, ev *Evaluator) {
548 assertArity("addsuffix", 2, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900549 abuf := newBuf()
550 fargs := ev.args(abuf, f.args[1:]...)
551 suf := fargs[0]
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900552 ws := newWordScanner(fargs[1])
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900553 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900554 for ws.Scan() {
555 sw.Write(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900556 // Use |w| not to append extra ' '.
557 w.Write(suf)
558 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900559 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900560}
561
562type funcAddprefix struct{ fclosure }
563
564func (f *funcAddprefix) Arity() int { return 2 }
565func (f *funcAddprefix) Eval(w io.Writer, ev *Evaluator) {
566 assertArity("addprefix", 2, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900567 abuf := newBuf()
568 fargs := ev.args(abuf, f.args[1:]...)
569 pre := fargs[0]
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900570 ws := newWordScanner(fargs[1])
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900571 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900572 for ws.Scan() {
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900573 sw.Write(pre)
574 // Use |w| not to append extra ' '.
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900575 w.Write(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900576 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900577 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900578}
579
580type funcRealpath struct{ fclosure }
581
582func (f *funcRealpath) Arity() int { return 1 }
583func (f *funcRealpath) Eval(w io.Writer, ev *Evaluator) {
584 assertArity("realpath", 1, len(f.args))
Shinichiro Hamajib41fd502015-04-29 03:34:07 +0900585 if ev.avoidIO {
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +0900586 w.Write([]byte("KATI_TODO(realpath)"))
Shinichiro Hamajib41fd502015-04-29 03:34:07 +0900587 ev.hasIO = true
588 return
589 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900590 abuf := newBuf()
591 f.args[1].Eval(abuf, ev)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900592 ws := newWordScanner(abuf.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900593 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900594 for ws.Scan() {
595 name := string(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900596 name, err := filepath.Abs(name)
597 if err != nil {
598 Log("abs: %v", err)
599 continue
600 }
601 name, err = filepath.EvalSymlinks(name)
602 if err != nil {
603 Log("realpath: %v", err)
604 continue
605 }
Shinichiro Hamajia1358912015-04-11 12:16:21 +0900606 sw.WriteString(name)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900607 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900608 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900609}
610
611type funcAbspath struct{ fclosure }
612
613func (f *funcAbspath) Arity() int { return 1 }
614func (f *funcAbspath) Eval(w io.Writer, ev *Evaluator) {
615 assertArity("abspath", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900616 abuf := newBuf()
617 f.args[1].Eval(abuf, ev)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900618 ws := newWordScanner(abuf.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900619 sw := ssvWriter{w: w}
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900620 for ws.Scan() {
621 name := string(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900622 name, err := filepath.Abs(name)
623 if err != nil {
624 Log("abs: %v", err)
625 continue
626 }
Shinichiro Hamajia1358912015-04-11 12:16:21 +0900627 sw.WriteString(name)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900628 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900629 freeBuf(abuf)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900630}
631
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900632// http://www.gnu.org/software/make/manual/make.html#Conditional-Functions
633type funcIf struct{ fclosure }
634
635func (f *funcIf) Arity() int { return 3 }
636func (f *funcIf) Eval(w io.Writer, ev *Evaluator) {
637 assertArity("if", 2, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900638 abuf := newBuf()
639 f.args[1].Eval(abuf, ev)
640 if len(abuf.Bytes()) != 0 {
641 freeBuf(abuf)
Fumitoshi Ukaie27a25d2015-04-18 00:31:01 +0900642 f.args[2].Eval(w, ev)
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900643 return
644 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900645 freeBuf(abuf)
Fumitoshi Ukaie27a25d2015-04-18 00:31:01 +0900646 if len(f.args) > 3 {
647 f.args[3].Eval(w, ev)
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900648 }
649}
650
651type funcAnd struct{ fclosure }
652
653func (f *funcAnd) Arity() int { return 0 }
654func (f *funcAnd) Eval(w io.Writer, ev *Evaluator) {
655 assertArity("and", 0, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900656 abuf := newBuf()
Shinichiro Hamaji2216dd62015-04-11 13:44:39 +0900657 var cond []byte
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900658 for _, arg := range f.args[1:] {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900659 abuf.Reset()
660 arg.Eval(abuf, ev)
661 cond = abuf.Bytes()
Shinichiro Hamaji2216dd62015-04-11 13:44:39 +0900662 if len(cond) == 0 {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900663 freeBuf(abuf)
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900664 return
665 }
666 }
Shinichiro Hamaji2216dd62015-04-11 13:44:39 +0900667 w.Write(cond)
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900668 freeBuf(abuf)
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900669}
670
671type funcOr struct{ fclosure }
672
673func (f *funcOr) Arity() int { return 0 }
674func (f *funcOr) Eval(w io.Writer, ev *Evaluator) {
675 assertArity("or", 0, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900676 abuf := newBuf()
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900677 for _, arg := range f.args[1:] {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900678 abuf.Reset()
679 arg.Eval(abuf, ev)
680 cond := abuf.Bytes()
Shinichiro Hamaji2216dd62015-04-11 13:44:39 +0900681 if len(cond) != 0 {
682 w.Write(cond)
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900683 freeBuf(abuf)
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900684 return
685 }
686 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900687 freeBuf(abuf)
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900688}
689
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900690// http://www.gnu.org/software/make/manual/make.html#Shell-Function
691type funcShell struct{ fclosure }
692
Fumitoshi Ukai586b02a2015-05-08 00:23:10 +0900693var shellFuncTime time.Duration
694
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900695func (f *funcShell) Arity() int { return 1 }
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900696
Shinichiro Hamajic0095e32015-05-27 18:49:06 +0900697// A hack for Android build. We need to evaluate things like $((3+4))
698// when we emit ninja file, because the result of such expressions
699// will be passed to other make functions.
700// TODO: Maybe we should modify Android's Makefile and remove this
701// workaround. It would be also nice if we can detect things like
702// this.
703func hasNoIoInShellScript(s []byte) bool {
704 if len(s) == 0 {
705 return true
706 }
707 if !bytes.HasPrefix(s, []byte("echo $((")) || s[len(s)-1] != ')' {
708 return false
709 }
Shinichiro Hamaji80017a02015-05-27 18:56:38 +0900710 Log("has no IO - evaluate now: %s", s)
Shinichiro Hamajic0095e32015-05-27 18:49:06 +0900711 return true
712}
713
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900714func (f *funcShell) Eval(w io.Writer, ev *Evaluator) {
715 assertArity("shell", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900716 abuf := newBuf()
717 f.args[1].Eval(abuf, ev)
Shinichiro Hamajic0095e32015-05-27 18:49:06 +0900718 if ev.avoidIO && !hasNoIoInShellScript(abuf.Bytes()) {
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +0900719 ev.hasIO = true
720 w.Write([]byte("$("))
721 w.Write(abuf.Bytes())
722 w.Write([]byte{')'})
723 return
724 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900725 arg := abuf.String()
726 freeBuf(abuf)
Shinichiro Hamaji89551c92015-04-11 19:33:03 +0900727 shellVar := ev.LookupVar("SHELL")
728 // TODO: Should be Eval, not String.
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900729 cmdline := []string{shellVar.String(), "-c", arg}
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900730 cmd := exec.Cmd{
731 Path: cmdline[0],
732 Args: cmdline,
733 Stderr: os.Stderr,
734 }
Fumitoshi Ukai586b02a2015-05-08 00:23:10 +0900735 t := time.Now()
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900736 out, err := cmd.Output()
Fumitoshi Ukai586b02a2015-05-08 00:23:10 +0900737 shellFuncTime += time.Now().Sub(t)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900738 if err != nil {
739 Log("$(shell %q) failed: %q", arg, err)
740 }
741
Shinichiro Hamajiba6b84d2015-06-03 18:46:13 +0900742 w.Write(formatCommandOutput(out))
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900743}
744
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +0900745// https://www.gnu.org/software/make/manual/html_node/Call-Function.html#Call-Function
746type funcCall struct{ fclosure }
747
748func (f *funcCall) Arity() int { return 0 }
749
750func (f *funcCall) Eval(w io.Writer, ev *Evaluator) {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900751 abuf := newBuf()
752 fargs := ev.args(abuf, f.args[1:]...)
753 variable := fargs[0]
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900754 Log("call %q variable %q", f.args[1], variable)
755 v := ev.LookupVar(string(variable))
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +0900756 // Evalualte all arguments first before we modify the table.
Shinichiro Hamaji39728f12015-04-11 20:12:23 +0900757 var args []tmpval
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900758 // $0 is variable.
759 args = append(args, tmpval(variable))
760 // TODO(ukai): If variable is the name of a built-in function,
761 // the built-in function is always invoked (even if a make variable
762 // by that name also exists).
763
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900764 for i, arg := range fargs[1:] {
765 // f.args[2]=>args[1] will be $1.
766 args = append(args, tmpval(arg))
767 Log("call $%d: %q=>%q", i+1, arg, fargs[i+1])
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +0900768 }
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900769 oldParams := ev.paramVars
770 ev.paramVars = args
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +0900771
Fumitoshi Ukai9b10ecf2015-04-15 17:45:50 +0900772 var restores []func()
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +0900773 for i, arg := range args {
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900774 name := fmt.Sprintf("%d", i)
Fumitoshi Ukai9b10ecf2015-04-15 17:45:50 +0900775 restores = append(restores, ev.outVars.save(name))
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900776 ev.outVars.Assign(name, SimpleVar{
777 value: arg,
778 origin: "automatic", // ??
779 })
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +0900780 }
781
782 var buf bytes.Buffer
Fumitoshi Ukaie27a25d2015-04-18 00:31:01 +0900783 if katiLogFlag {
784 w = io.MultiWriter(w, &buf)
785 }
786 v.Eval(w, ev)
Fumitoshi Ukai9b10ecf2015-04-15 17:45:50 +0900787 for _, restore := range restores {
788 restore()
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +0900789 }
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900790 ev.paramVars = oldParams
791 Log("call %q variable %q return %q", f.args[1], variable, buf.Bytes())
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900792 freeBuf(abuf)
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +0900793}
794
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +0900795// http://www.gnu.org/software/make/manual/make.html#Value-Function
796type funcValue struct{ fclosure }
797
798func (f *funcValue) Arity() int { return 1 }
799func (f *funcValue) Eval(w io.Writer, ev *Evaluator) {
800 assertArity("value", 1, len(f.args))
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900801 v := ev.LookupVar(f.args[1].String())
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +0900802 w.Write([]byte(v.String()))
803}
804
805// http://www.gnu.org/software/make/manual/make.html#Eval-Function
806type funcEval struct{ fclosure }
807
808func (f *funcEval) Arity() int { return 1 }
809func (f *funcEval) Eval(w io.Writer, ev *Evaluator) {
810 assertArity("eval", 1, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900811 abuf := newBuf()
812 f.args[1].Eval(abuf, ev)
813 s := abuf.Bytes()
814 Log("eval %q at %s:%d", s, ev.filename, ev.lineno)
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +0900815 mk, err := ParseMakefileBytes(s, ev.filename, ev.lineno)
816 if err != nil {
817 panic(err)
818 }
819
820 for _, stmt := range mk.stmts {
821 ev.eval(stmt)
822 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900823 freeBuf(abuf)
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +0900824}
825
Fumitoshi Ukai9f6b6352015-04-16 16:25:09 +0900826func (f *funcEval) Compact() Value {
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900827 if len(f.args)-1 < 1 {
828 return f
829 }
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900830 switch arg := f.args[1].(type) {
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900831 case literal, tmpval:
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900832 case Expr:
833 if len(arg) == 1 {
834 return f
835 }
836 switch prefix := arg[0].(type) {
837 case literal, tmpval:
838 lhs, op, rhsprefix, ok := parseAssignLiteral(prefix.String())
839 if ok {
840 // $(eval foo = $(bar))
841 var rhs Expr
842 if rhsprefix != literal("") {
843 rhs = append(rhs, rhsprefix)
844 }
845 rhs = append(rhs, arg[1:]...)
846 Log("eval assign %#v => lhs:%q op:%q rhs:%#v", f, lhs, op, rhs)
847 return &funcEvalAssign{
848 lhs: lhs,
849 op: op,
850 rhs: compactExpr(rhs),
851 }
852 }
853 }
854 // TODO(ukai): eval -> varassign. e.g $(eval $(foo) := $(x)).
Fumitoshi Ukai769157a2015-06-02 15:18:53 +0900855 return f
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900856 default:
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900857 return f
858 }
859 arg := f.args[1].String()
860 arg = stripComment(arg)
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900861 if arg == "" || strings.TrimSpace(arg) == "" {
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900862 return &funcNop{expr: f.String()}
863 }
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900864 f.args[1] = literal(arg)
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900865 lhs, op, rhs, ok := parseAssignLiteral(f.args[1].String())
866 if ok {
Fumitoshi Ukai150c8612015-04-16 15:35:44 +0900867 return &funcEvalAssign{
868 lhs: lhs,
869 op: op,
870 rhs: rhs,
871 }
872 }
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900873 return f
874}
875
876func stripComment(arg string) string {
877 for {
878 i := strings.Index(arg, "#")
879 if i < 0 {
880 return arg
881 }
882 eol := strings.Index(arg[i:], "\n")
883 if eol < 0 {
884 return arg[:i]
885 }
886 arg = arg[:i] + arg[eol+1:]
887 }
888}
889
890type funcNop struct{ expr string }
891
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900892func (f *funcNop) String() string { return f.expr }
893func (f *funcNop) Eval(io.Writer, *Evaluator) {}
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900894func (f *funcNop) Serialize() SerializableVar {
895 return SerializableVar{
896 Type: "funcNop",
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900897 V: f.expr,
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900898 }
899}
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900900func (f *funcNop) Dump(w io.Writer) {
901 dumpByte(w, VALUE_TYPE_NOP)
902}
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900903
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900904func parseAssignLiteral(s string) (lhs, op string, rhs Value, ok bool) {
905 eq := strings.Index(s, "=")
906 if eq < 0 {
907 return "", "", nil, false
908 }
909 // TODO(ukai): factor out parse assign?
910 lhs = s[:eq]
911 op = s[eq : eq+1]
912 if eq >= 1 && (s[eq-1] == ':' || s[eq-1] == '+' || s[eq-1] == '?') {
913 lhs = s[:eq-1]
914 op = s[eq-1 : eq+1]
915 }
916 lhs = strings.TrimSpace(lhs)
917 if strings.IndexAny(lhs, ":$") >= 0 {
918 // target specific var, or need eval.
919 return "", "", nil, false
920 }
921 r := strings.TrimLeft(s[eq+1:], " \t")
922 rhs = literal(r)
923 return lhs, op, rhs, true
924}
925
Fumitoshi Ukai150c8612015-04-16 15:35:44 +0900926type funcEvalAssign struct {
927 lhs string
928 op string
929 rhs Value
930}
931
Fumitoshi Ukai150c8612015-04-16 15:35:44 +0900932func (f *funcEvalAssign) String() string {
933 return fmt.Sprintf("$(eval %s %s %s)", f.lhs, f.op, f.rhs)
934}
935
936func (f *funcEvalAssign) Eval(w io.Writer, ev *Evaluator) {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900937 var abuf bytes.Buffer
938 f.rhs.Eval(&abuf, ev)
939 rhs := trimLeftSpaceBytes(abuf.Bytes())
Fumitoshi Ukai150c8612015-04-16 15:35:44 +0900940 var rvalue Var
941 switch f.op {
942 case ":=":
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900943 // TODO(ukai): compute parsed expr in Compact when f.rhs is
944 // literal? e.g. literal("$(foo)") => varref{literal("foo")}.
Fumitoshi Ukaifa5e9222015-04-17 11:45:20 +0900945 expr, _, err := parseExpr(rhs, nil)
946 if err != nil {
947 panic(fmt.Sprintf("eval assign error: %q: %v", f.String(), err))
948 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900949 abuf.Reset()
950 expr.Eval(&abuf, ev)
951 rvalue = SimpleVar{value: tmpval(abuf.Bytes()), origin: "file"}
Fumitoshi Ukai150c8612015-04-16 15:35:44 +0900952 case "=":
953 rvalue = RecursiveVar{expr: tmpval(rhs), origin: "file"}
954 case "+=":
955 prev := ev.LookupVar(f.lhs)
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900956 if prev.IsDefined() {
Fumitoshi Ukai150c8612015-04-16 15:35:44 +0900957 rvalue = prev.Append(ev, string(rhs))
958 } else {
959 rvalue = RecursiveVar{expr: tmpval(rhs), origin: "file"}
960 }
961 case "?=":
962 prev := ev.LookupVar(f.lhs)
963 if prev.IsDefined() {
964 return
965 }
966 rvalue = RecursiveVar{expr: tmpval(rhs), origin: "file"}
967 }
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900968 Log("Eval ASSIGN: %s=%q (flavor:%q)", f.lhs, rvalue, rvalue.Flavor())
Fumitoshi Ukai150c8612015-04-16 15:35:44 +0900969 ev.outVars.Assign(f.lhs, rvalue)
970}
971
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900972func (f *funcEvalAssign) Serialize() SerializableVar {
973 return SerializableVar{
974 Type: "funcEvalAssign",
975 Children: []SerializableVar{
976 SerializableVar{V: f.lhs},
977 SerializableVar{V: f.op},
978 f.rhs.Serialize(),
979 },
980 }
981}
982
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900983func (f *funcEvalAssign) Dump(w io.Writer) {
984 dumpByte(w, VALUE_TYPE_ASSIGN)
985 dumpString(w, f.lhs)
986 dumpString(w, f.op)
987 f.rhs.Dump(w)
988}
989
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +0900990// http://www.gnu.org/software/make/manual/make.html#Origin-Function
991type funcOrigin struct{ fclosure }
992
993func (f *funcOrigin) Arity() int { return 1 }
994func (f *funcOrigin) Eval(w io.Writer, ev *Evaluator) {
995 assertArity("origin", 1, len(f.args))
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900996 v := ev.LookupVar(f.args[1].String())
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +0900997 w.Write([]byte(v.Origin()))
998}
999
1000// https://www.gnu.org/software/make/manual/html_node/Flavor-Function.html#Flavor-Function
1001type funcFlavor struct{ fclosure }
1002
1003func (f *funcFlavor) Arity() int { return 1 }
1004func (f *funcFlavor) Eval(w io.Writer, ev *Evaluator) {
1005 assertArity("flavor", 1, len(f.args))
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +09001006 v := ev.LookupVar(f.args[1].String())
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001007 w.Write([]byte(v.Flavor()))
1008}
1009
1010// http://www.gnu.org/software/make/manual/make.html#Make-Control-Functions
1011type funcInfo struct{ fclosure }
1012
1013func (f *funcInfo) Arity() int { return 1 }
1014func (f *funcInfo) Eval(w io.Writer, ev *Evaluator) {
1015 assertArity("info", 1, len(f.args))
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001016 if ev.avoidIO {
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +09001017 w.Write([]byte("KATI_TODO(info)"))
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001018 ev.hasIO = true
1019 return
1020 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001021 abuf := newBuf()
1022 f.args[1].Eval(abuf, ev)
1023 fmt.Printf("%s\n", abuf.String())
1024 freeBuf(abuf)
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001025}
1026
1027type funcWarning struct{ fclosure }
1028
1029func (f *funcWarning) Arity() int { return 1 }
1030func (f *funcWarning) Eval(w io.Writer, ev *Evaluator) {
1031 assertArity("warning", 1, len(f.args))
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001032 if ev.avoidIO {
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +09001033 w.Write([]byte("KATI_TODO(warning)"))
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001034 ev.hasIO = true
1035 return
1036 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001037 abuf := newBuf()
1038 f.args[1].Eval(abuf, ev)
1039 fmt.Printf("%s:%d: %s\n", ev.filename, ev.lineno, abuf.String())
1040 freeBuf(abuf)
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001041}
1042
1043type funcError struct{ fclosure }
1044
1045func (f *funcError) Arity() int { return 1 }
1046func (f *funcError) Eval(w io.Writer, ev *Evaluator) {
1047 assertArity("error", 1, len(f.args))
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001048 if ev.avoidIO {
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +09001049 w.Write([]byte("KATI_TODO(error)"))
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001050 ev.hasIO = true
1051 return
1052 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001053 abuf := newBuf()
1054 f.args[1].Eval(abuf, ev)
1055 Error(ev.filename, ev.lineno, "*** %s.", abuf.String())
1056 freeBuf(abuf)
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001057}
1058
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001059// http://www.gnu.org/software/make/manual/make.html#Foreach-Function
1060type funcForeach struct{ fclosure }
1061
1062func (f *funcForeach) Arity() int { return 3 }
1063
1064func (f *funcForeach) Eval(w io.Writer, ev *Evaluator) {
1065 assertArity("foreach", 3, len(f.args))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001066 abuf := newBuf()
1067 fargs := ev.args(abuf, f.args[1], f.args[2])
1068 varname := string(fargs[0])
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +09001069 ws := newWordScanner(fargs[1])
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +09001070 text := f.args[3]
Fumitoshi Ukai9b10ecf2015-04-15 17:45:50 +09001071 restore := ev.outVars.save(varname)
1072 defer restore()
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001073 space := false
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +09001074 for ws.Scan() {
1075 word := ws.Bytes()
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001076 ev.outVars.Assign(varname,
1077 SimpleVar{
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001078 value: tmpval(word),
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001079 origin: "automatic",
1080 })
1081 if space {
1082 w.Write([]byte{' '})
1083 }
Fumitoshi Ukaie27a25d2015-04-18 00:31:01 +09001084 text.Eval(w, ev)
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001085 space = true
1086 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001087 freeBuf(abuf)
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001088}