blob: d390409390218ecdf43235a0ff803a5e1d9a7ab3 [file] [log] [blame]
Shinichiro Hamajib69bf8a2015-06-10 14:52:06 +09001// Copyright 2015 Google Inc. All rights reserved
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +090015package kati
Fumitoshi Ukaif2f84562015-03-30 19:47:45 +090016
17import (
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090018 "bytes"
Fumitoshi Ukaif2f84562015-03-30 19:47:45 +090019 "fmt"
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090020 "io"
Shinichiro Hamajie7aafb02015-04-09 18:23:46 +090021 "os"
Fumitoshi Ukaif2f84562015-03-30 19:47:45 +090022 "os/exec"
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +090023 "path/filepath"
Shinichiro Hamaji13b30d92015-04-03 14:42:21 +090024 "sort"
Shinichiro Hamajie708a9d2015-04-03 14:34:35 +090025 "strconv"
Fumitoshi Ukaif2f84562015-03-30 19:47:45 +090026 "strings"
Fumitoshi Ukai586b02a2015-05-08 00:23:10 +090027 "time"
Fumitoshi Ukaif2f84562015-03-30 19:47:45 +090028)
29
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090030// mkFunc is a make function.
Fumitoshi Ukaif2f84562015-03-30 19:47:45 +090031// http://www.gnu.org/software/make/manual/make.html#Functions
Fumitoshi Ukaie520f262015-03-31 17:27:03 +090032
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090033// mkFunc is make builtin function.
34type mkFunc interface {
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090035 // Arity is max function's arity.
36 // ',' will not be handled as argument separator more than arity.
37 // 0 means varargs.
38 Arity() int
39
40 // AddArg adds value as an argument.
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +090041 // the first argument will be "(funcname", or "{funcname".
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090042 AddArg(Value)
43
44 Value
45}
46
47var (
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090048 funcMap = map[string]func() mkFunc{
49 "patsubst": func() mkFunc { return &funcPatsubst{} },
50 "strip": func() mkFunc { return &funcStrip{} },
51 "subst": func() mkFunc { return &funcSubst{} },
52 "findstring": func() mkFunc { return &funcFindstring{} },
53 "filter": func() mkFunc { return &funcFilter{} },
54 "filter-out": func() mkFunc { return &funcFilterOut{} },
55 "sort": func() mkFunc { return &funcSort{} },
56 "word": func() mkFunc { return &funcWord{} },
57 "wordlist": func() mkFunc { return &funcWordlist{} },
58 "words": func() mkFunc { return &funcWords{} },
59 "firstword": func() mkFunc { return &funcFirstword{} },
60 "lastword": func() mkFunc { return &funcLastword{} },
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +090061
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090062 "join": func() mkFunc { return &funcJoin{} },
63 "wildcard": func() mkFunc { return &funcWildcard{} },
64 "dir": func() mkFunc { return &funcDir{} },
65 "notdir": func() mkFunc { return &funcNotdir{} },
66 "suffix": func() mkFunc { return &funcSuffix{} },
67 "basename": func() mkFunc { return &funcBasename{} },
68 "addsuffix": func() mkFunc { return &funcAddsuffix{} },
69 "addprefix": func() mkFunc { return &funcAddprefix{} },
70 "realpath": func() mkFunc { return &funcRealpath{} },
71 "abspath": func() mkFunc { return &funcAbspath{} },
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +090072
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090073 "if": func() mkFunc { return &funcIf{} },
74 "and": func() mkFunc { return &funcAnd{} },
75 "or": func() mkFunc { return &funcOr{} },
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +090076
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090077 "value": func() mkFunc { return &funcValue{} },
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +090078
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090079 "eval": func() mkFunc { return &funcEval{} },
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +090080
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090081 "shell": func() mkFunc { return &funcShell{} },
82 "call": func() mkFunc { return &funcCall{} },
83 "foreach": func() mkFunc { return &funcForeach{} },
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +090084
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090085 "origin": func() mkFunc { return &funcOrigin{} },
86 "flavor": func() mkFunc { return &funcFlavor{} },
87 "info": func() mkFunc { return &funcInfo{} },
88 "warning": func() mkFunc { return &funcWarning{} },
89 "error": func() mkFunc { return &funcError{} },
Fumitoshi Ukai0b5e18b2015-04-03 22:57:17 +090090 }
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090091)
92
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090093type arityError struct {
94 narg int
95 name string
96}
97
98func (e arityError) Error() string {
99 return fmt.Sprintf("*** insufficient number of arguments (%d) to function `%s'.", e.narg, e.name)
100}
101
102func assertArity(name string, req, n int) error {
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900103 if n-1 < req {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900104 return arityError{narg: n - 1, name: name}
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900105 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900106 return nil
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900107}
108
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900109func numericValueForFunc(v string) (int, bool) {
110 n, err := strconv.Atoi(v)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900111 if err != nil || n < 0 {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900112 return n, false
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900113 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900114 return n, true
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900115}
116
Shinichiro Hamajiba6b84d2015-06-03 18:46:13 +0900117func formatCommandOutput(out []byte) []byte {
118 out = bytes.TrimRight(out, "\n")
119 out = bytes.Replace(out, []byte{'\n'}, []byte{' '}, -1)
120 return out
121}
122
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900123type fclosure struct {
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900124 // args[0] is "(funcname", or "{funcname".
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900125 args []Value
126}
127
128func (c *fclosure) AddArg(v Value) {
129 c.args = append(c.args, v)
Fumitoshi Ukai0b5e18b2015-04-03 22:57:17 +0900130}
131
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900132func (c *fclosure) String() string {
133 if len(c.args) == 0 {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900134 return "$(func)"
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900135 }
136 arg0 := c.args[0].String()
137 if arg0 == "" {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900138 return "$(func )"
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900139 }
140 cp := closeParen(arg0[0])
141 if cp == 0 {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900142 return "${func }"
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900143 }
144 var args []string
145 for _, arg := range c.args[1:] {
146 args = append(args, arg.String())
147 }
148 return fmt.Sprintf("$%s %s%c", arg0, strings.Join(args, ","), cp)
149}
Fumitoshi Ukai78781132015-04-10 17:08:40 +0900150
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900151func (c *fclosure) serialize() serializableVar {
152 r := serializableVar{Type: "func"}
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900153 for _, a := range c.args {
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900154 r.Children = append(r.Children, a.serialize())
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900155 }
156 return r
157}
158
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900159func (c *fclosure) dump(d *dumpbuf) {
160 d.Byte(valueTypeFunc)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900161 for _, a := range c.args {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900162 a.dump(d)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900163 }
164}
165
Shinichiro Hamaji4125cf42015-04-03 11:42:28 +0900166// http://www.gnu.org/software/make/manual/make.html#Text-Functions
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900167type funcSubst struct{ fclosure }
168
169func (f *funcSubst) Arity() int { return 3 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900170func (f *funcSubst) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900171 err := assertArity("subst", 3, len(f.args))
172 if err != nil {
173 return err
174 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900175 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900176 fargs, err := ev.args(abuf, f.args[1:]...)
177 if err != nil {
178 return err
179 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900180 t := time.Now()
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900181 from := fargs[0]
182 to := fargs[1]
183 text := fargs[2]
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900184 logf("subst from:%q to:%q text:%q", from, to, text)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900185 w.Write(bytes.Replace(text, from, to, -1))
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900186 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900187 stats.add("funcbody", "subst", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900188 return nil
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900189}
190
Shinichiro Hamaji98e910d2015-04-11 10:38:44 +0900191type funcPatsubst struct{ fclosure }
192
193func (f *funcPatsubst) Arity() int { return 3 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900194func (f *funcPatsubst) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900195 err := assertArity("patsubst", 3, len(f.args))
196 if err != nil {
197 return err
198 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900199 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900200 fargs, err := ev.args(abuf, f.args[1:]...)
201 if err != nil {
202 return err
203 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900204 t := time.Now()
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900205 pat := fargs[0]
206 repl := fargs[1]
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900207 ws := newWordScanner(fargs[2])
Fumitoshi Ukai77411fb2015-06-19 15:46:21 +0900208 space := false
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900209 for ws.Scan() {
Fumitoshi Ukai77411fb2015-06-19 15:46:21 +0900210 if space {
211 writeByte(w, ' ')
212 }
213 pre, subst, post := substPatternBytes(pat, repl, ws.Bytes())
214 w.Write(pre)
215 if subst != nil {
216 w.Write(subst)
217 w.Write(post)
218 }
219 space = true
Shinichiro Hamaji98e910d2015-04-11 10:38:44 +0900220 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900221 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900222 stats.add("funcbody", "patsubst", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900223 return nil
Shinichiro Hamaji98e910d2015-04-11 10:38:44 +0900224}
225
226type funcStrip struct{ fclosure }
227
228func (f *funcStrip) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900229func (f *funcStrip) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900230 err := assertArity("strip", 1, len(f.args))
231 if err != nil {
232 return err
233 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900234 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900235 err = f.args[1].Eval(abuf, ev)
236 if err != nil {
237 return err
238 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900239 t := time.Now()
Shinichiro Hamajib978e112015-06-05 11:02:45 +0900240 ws := newWordScanner(abuf.Bytes())
Fumitoshi Ukaia44b7662015-06-19 11:07:07 +0900241 space := false
Shinichiro Hamajib978e112015-06-05 11:02:45 +0900242 for ws.Scan() {
Fumitoshi Ukaia44b7662015-06-19 11:07:07 +0900243 if space {
244 writeByte(w, ' ')
245 }
246 w.Write(ws.Bytes())
247 space = true
Shinichiro Hamajib978e112015-06-05 11:02:45 +0900248 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900249 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900250 stats.add("funcbody", "strip", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900251 return nil
Shinichiro Hamaji98e910d2015-04-11 10:38:44 +0900252}
253
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900254type funcFindstring struct{ fclosure }
255
256func (f *funcFindstring) Arity() int { return 2 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900257func (f *funcFindstring) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900258 err := assertArity("findstring", 2, len(f.args))
259 if err != nil {
260 return err
261 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900262 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900263 fargs, err := ev.args(abuf, f.args[1:]...)
264 if err != nil {
265 return err
266 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900267 t := time.Now()
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900268 find := fargs[0]
269 text := fargs[1]
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900270 if bytes.Index(text, find) >= 0 {
271 w.Write(find)
272 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900273 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900274 stats.add("funcbody", "findstring", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900275 return nil
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900276}
277
278type funcFilter struct{ fclosure }
279
280func (f *funcFilter) Arity() int { return 2 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900281func (f *funcFilter) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900282 err := assertArity("filter", 2, len(f.args))
283 if err != nil {
284 return err
285 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900286 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900287 fargs, err := ev.args(abuf, f.args[1:]...)
288 if err != nil {
289 return err
290 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900291 t := time.Now()
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900292 var patterns [][]byte
293 ws := newWordScanner(fargs[0])
294 for ws.Scan() {
295 patterns = append(patterns, ws.Bytes())
296 }
297 ws = newWordScanner(fargs[1])
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900298 for ws.Scan() {
299 text := ws.Bytes()
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900300 for _, pat := range patterns {
301 if matchPatternBytes(pat, text) {
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900302 w.writeWord(text)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900303 }
304 }
305 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900306 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900307 stats.add("funcbody", "filter", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900308 return nil
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900309}
310
311type funcFilterOut struct{ fclosure }
312
313func (f *funcFilterOut) Arity() int { return 2 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900314func (f *funcFilterOut) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900315 err := assertArity("filter-out", 2, len(f.args))
316 if err != nil {
317 return err
318 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900319 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900320 fargs, err := ev.args(abuf, f.args[1:]...)
321 if err != nil {
322 return err
323 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900324 t := time.Now()
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900325 var patterns [][]byte
326 ws := newWordScanner(fargs[0])
327 for ws.Scan() {
328 patterns = append(patterns, ws.Bytes())
329 }
330 ws = newWordScanner(fargs[1])
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900331Loop:
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900332 for ws.Scan() {
333 text := ws.Bytes()
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900334 for _, pat := range patterns {
335 if matchPatternBytes(pat, text) {
336 continue Loop
337 }
338 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900339 w.writeWord(text)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900340 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900341 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900342 stats.add("funcbody", "filter-out", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900343 return err
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900344}
345
346type funcSort struct{ fclosure }
347
348func (f *funcSort) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900349func (f *funcSort) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900350 err := assertArity("sort", 1, len(f.args))
351 if err != nil {
352 return err
353 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900354 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900355 err = f.args[1].Eval(abuf, ev)
356 if err != nil {
357 return err
358 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900359 t := time.Now()
Fumitoshi Ukai79cfbab2015-06-18 23:28:26 +0900360 ws := newWordScanner(abuf.Bytes())
361 var toks []string
362 for ws.Scan() {
363 toks = append(toks, string(ws.Bytes()))
364 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900365 freeBuf(abuf)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900366 sort.Strings(toks)
367
368 // Remove duplicate words.
369 var prev string
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900370 for _, tok := range toks {
Fumitoshi Ukaice14acb2015-06-19 13:54:53 +0900371 if prev == tok {
372 continue
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900373 }
Fumitoshi Ukaice14acb2015-06-19 13:54:53 +0900374 if prev != "" {
375 writeByte(w, ' ')
376 }
377 io.WriteString(w, tok)
378 prev = tok
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900379 }
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900380 stats.add("funcbody", "sort", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900381 return nil
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900382}
383
384type funcWord struct{ fclosure }
385
386func (f *funcWord) Arity() int { return 2 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900387func (f *funcWord) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900388 err := assertArity("word", 2, len(f.args))
389 if err != nil {
390 return err
391 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900392 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900393 fargs, err := ev.args(abuf, f.args[1:]...)
394 if err != nil {
395 return err
396 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900397 t := time.Now()
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900398 v := string(trimSpaceBytes(fargs[0]))
399 index, ok := numericValueForFunc(v)
400 if !ok {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900401 return ev.errorf(`*** non-numeric first argument to "word" function: %q.`, v)
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900402 }
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900403 if index == 0 {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900404 return ev.errorf(`*** first argument to "word" function must be greater than 0.`)
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900405 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900406 ws := newWordScanner(fargs[1])
407 for ws.Scan() {
408 index--
409 if index == 0 {
410 w.Write(ws.Bytes())
411 break
412 }
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900413 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900414 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900415 stats.add("funcbody", "word", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900416 return err
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900417}
418
419type funcWordlist struct{ fclosure }
420
421func (f *funcWordlist) Arity() int { return 3 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900422func (f *funcWordlist) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900423 err := assertArity("wordlist", 3, len(f.args))
424 if err != nil {
425 return err
426 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900427 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900428 fargs, err := ev.args(abuf, f.args[1:]...)
429 if err != nil {
430 return err
431 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900432 t := time.Now()
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900433 v := string(trimSpaceBytes(fargs[0]))
434 si, ok := numericValueForFunc(v)
435 if !ok {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900436 return ev.errorf(`*** non-numeric first argument to "wordlist" function: %q.`, v)
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900437 }
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900438 if si == 0 {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900439 return ev.errorf(`*** invalid first argument to "wordlist" function: %s`, f.args[1])
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900440 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900441 v = string(trimSpaceBytes(fargs[1]))
442 ei, ok := numericValueForFunc(v)
443 if !ok {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900444 return ev.errorf(`*** non-numeric second argument to "wordlist" function: %q.`, v)
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900445 }
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900446
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900447 ws := newWordScanner(fargs[2])
448 i := 0
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900449 for ws.Scan() {
450 i++
451 if si <= i && i <= ei {
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900452 w.writeWord(ws.Bytes())
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900453 }
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900454 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900455 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900456 stats.add("funcbody", "wordlist", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900457 return nil
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900458}
459
460type funcWords struct{ fclosure }
461
462func (f *funcWords) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900463func (f *funcWords) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900464 err := assertArity("words", 1, len(f.args))
465 if err != nil {
466 return err
467 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900468 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900469 err = f.args[1].Eval(abuf, ev)
470 if err != nil {
471 return err
472 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900473 t := time.Now()
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900474 ws := newWordScanner(abuf.Bytes())
475 n := 0
476 for ws.Scan() {
477 n++
478 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900479 freeBuf(abuf)
Fumitoshi Ukai145598a2015-06-19 10:08:17 +0900480 io.WriteString(w, strconv.Itoa(n))
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900481 stats.add("funcbody", "words", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900482 return nil
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900483}
484
485type funcFirstword struct{ fclosure }
486
487func (f *funcFirstword) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900488func (f *funcFirstword) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900489 err := assertArity("firstword", 1, len(f.args))
490 if err != nil {
491 return err
492 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900493 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900494 err = f.args[1].Eval(abuf, ev)
495 if err != nil {
496 return err
497 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900498 t := time.Now()
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900499 ws := newWordScanner(abuf.Bytes())
500 if ws.Scan() {
501 w.Write(ws.Bytes())
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900502 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900503 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900504 stats.add("funcbody", "firstword", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900505 return nil
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900506}
507
508type funcLastword struct{ fclosure }
509
510func (f *funcLastword) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900511func (f *funcLastword) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900512 err := assertArity("lastword", 1, len(f.args))
513 if err != nil {
514 return err
515 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900516 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900517 err = f.args[1].Eval(abuf, ev)
518 if err != nil {
519 return err
520 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900521 t := time.Now()
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900522 ws := newWordScanner(abuf.Bytes())
523 var lw []byte
524 for ws.Scan() {
525 lw = ws.Bytes()
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900526 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900527 if lw != nil {
528 w.Write(lw)
529 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900530 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900531 stats.add("funcbody", "lastword", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900532 return err
Shinichiro Hamaji05b222d2015-04-11 11:36:37 +0900533}
534
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900535// https://www.gnu.org/software/make/manual/html_node/File-Name-Functions.html#File-Name-Functions
536
537type funcJoin struct{ fclosure }
538
539func (f *funcJoin) Arity() int { return 2 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900540func (f *funcJoin) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900541 err := assertArity("join", 2, len(f.args))
542 if err != nil {
543 return err
544 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900545 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900546 fargs, err := ev.args(abuf, f.args[1:]...)
547 if err != nil {
548 return err
549 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900550 t := time.Now()
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900551 ws1 := newWordScanner(fargs[0])
552 ws2 := newWordScanner(fargs[1])
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900553 for {
554 if w1, w2 := ws1.Scan(), ws2.Scan(); !w1 && !w2 {
555 break
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900556 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900557 var word []byte
558 word = append(word, ws1.Bytes()...)
559 word = append(word, ws2.Bytes()...)
560 w.writeWord(word)
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900561 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900562 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900563 stats.add("funcbody", "join", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900564 return nil
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900565}
566
567type funcWildcard struct{ fclosure }
568
569func (f *funcWildcard) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900570func (f *funcWildcard) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900571 err := assertArity("wildcard", 1, len(f.args))
572 if err != nil {
573 return err
574 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900575 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900576 err = f.args[1].Eval(abuf, ev)
577 if err != nil {
578 return err
579 }
Fumitoshi Ukai83410132015-06-15 14:50:07 +0900580 te := traceEvent.begin("wildcard", tmpval(abuf.Bytes()), traceEventMain)
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900581 if ev.avoidIO && !UseWildcardCache {
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +0900582 ev.hasIO = true
Fumitoshi Ukai145598a2015-06-19 10:08:17 +0900583 io.WriteString(w, "$(/bin/ls -d ")
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +0900584 w.Write(abuf.Bytes())
Fumitoshi Ukai145598a2015-06-19 10:08:17 +0900585 io.WriteString(w, " 2> /dev/null)")
Fumitoshi Ukai432a2422015-06-11 15:16:29 +0900586 traceEvent.end(te)
Fumitoshi Ukai358c68a2015-06-08 13:12:55 +0900587 freeBuf(abuf)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900588 return nil
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +0900589 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900590 t := time.Now()
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900591 ws := newWordScanner(abuf.Bytes())
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900592 for ws.Scan() {
Shinichiro Hamajiba6b84d2015-06-03 18:46:13 +0900593 pat := string(ws.Bytes())
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900594 err = wildcard(w, pat)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900595 if err != nil {
596 return err
597 }
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900598 }
Fumitoshi Ukai432a2422015-06-11 15:16:29 +0900599 traceEvent.end(te)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900600 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900601 stats.add("funcbody", "wildcard", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900602 return nil
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900603}
604
605type funcDir struct{ fclosure }
606
607func (f *funcDir) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900608func (f *funcDir) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900609 err := assertArity("dir", 1, len(f.args))
610 if err != nil {
611 return err
612 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900613 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900614 err = f.args[1].Eval(abuf, ev)
615 if err != nil {
616 return err
617 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900618 t := time.Now()
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900619 ws := newWordScanner(abuf.Bytes())
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900620 for ws.Scan() {
Shinichiro Hamaji55906852015-06-29 16:40:33 +0900621 name := filepath.Dir(string(string(ws.Bytes())))
Shinichiro Hamaji37626b62015-04-21 16:59:23 +0900622 if name == "/" {
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900623 w.writeWordString(name)
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900624 continue
Shinichiro Hamaji37626b62015-04-21 16:59:23 +0900625 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900626 w.writeWordString(name + string(filepath.Separator))
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900627 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900628 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900629 stats.add("funcbody", "dir", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900630 return nil
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900631}
632
633type funcNotdir struct{ fclosure }
634
635func (f *funcNotdir) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900636func (f *funcNotdir) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900637 err := assertArity("notdir", 1, len(f.args))
638 if err != nil {
639 return err
640 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900641 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900642 err = f.args[1].Eval(abuf, ev)
643 if err != nil {
644 return err
645 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900646 t := time.Now()
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900647 ws := newWordScanner(abuf.Bytes())
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900648 for ws.Scan() {
649 name := string(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900650 if name == string(filepath.Separator) {
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900651 w.writeWord([]byte{}) // separator
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900652 continue
653 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900654 w.writeWordString(filepath.Base(name))
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900655 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900656 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900657 stats.add("funcbody", "notdir", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900658 return nil
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900659}
660
661type funcSuffix struct{ fclosure }
662
663func (f *funcSuffix) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900664func (f *funcSuffix) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900665 err := assertArity("suffix", 1, len(f.args))
666 if err != nil {
667 return err
668 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900669 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900670 err = f.args[1].Eval(abuf, ev)
671 if err != nil {
672 return err
673 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900674 t := time.Now()
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900675 ws := newWordScanner(abuf.Bytes())
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900676 for ws.Scan() {
677 tok := string(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900678 e := filepath.Ext(tok)
679 if len(e) > 0 {
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900680 w.writeWordString(e)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900681 }
682 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900683 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900684 stats.add("funcbody", "suffix", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900685 return err
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900686}
687
688type funcBasename struct{ fclosure }
689
690func (f *funcBasename) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900691func (f *funcBasename) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900692 err := assertArity("basename", 1, len(f.args))
693 if err != nil {
694 return err
695 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900696 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900697 err = f.args[1].Eval(abuf, ev)
698 if err != nil {
699 return err
700 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900701 t := time.Now()
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900702 ws := newWordScanner(abuf.Bytes())
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900703 for ws.Scan() {
704 tok := string(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900705 e := stripExt(tok)
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900706 w.writeWordString(e)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900707 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900708 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900709 stats.add("funcbody", "basename", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900710 return nil
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900711}
712
713type funcAddsuffix struct{ fclosure }
714
715func (f *funcAddsuffix) Arity() int { return 2 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900716func (f *funcAddsuffix) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900717 err := assertArity("addsuffix", 2, len(f.args))
718 if err != nil {
719 return err
720 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900721 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900722 fargs, err := ev.args(abuf, f.args[1:]...)
723 if err != nil {
724 return err
725 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900726 t := time.Now()
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900727 suf := fargs[0]
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900728 ws := newWordScanner(fargs[1])
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900729 for ws.Scan() {
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900730 var name []byte
731 name = append(name, ws.Bytes()...)
732 name = append(name, suf...)
733 w.writeWord(name)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900734 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900735 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900736 stats.add("funcbody", "addsuffix", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900737 return err
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900738}
739
740type funcAddprefix struct{ fclosure }
741
742func (f *funcAddprefix) Arity() int { return 2 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900743func (f *funcAddprefix) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900744 err := assertArity("addprefix", 2, len(f.args))
745 if err != nil {
746 return err
747 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900748 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900749 fargs, err := ev.args(abuf, f.args[1:]...)
750 if err != nil {
751 return err
752 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900753 t := time.Now()
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900754 pre := fargs[0]
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900755 ws := newWordScanner(fargs[1])
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900756 for ws.Scan() {
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900757 var name []byte
758 name = append(name, pre...)
759 name = append(name, ws.Bytes()...)
760 w.writeWord(name)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900761 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900762 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900763 stats.add("funcbody", "addprefix", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900764 return err
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900765}
766
767type funcRealpath struct{ fclosure }
768
769func (f *funcRealpath) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900770func (f *funcRealpath) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900771 err := assertArity("realpath", 1, len(f.args))
772 if err != nil {
773 return err
774 }
Shinichiro Hamajib41fd502015-04-29 03:34:07 +0900775 if ev.avoidIO {
Fumitoshi Ukai145598a2015-06-19 10:08:17 +0900776 io.WriteString(w, "KATI_TODO(realpath)")
Shinichiro Hamajib41fd502015-04-29 03:34:07 +0900777 ev.hasIO = true
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900778 return nil
Shinichiro Hamajib41fd502015-04-29 03:34:07 +0900779 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900780 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900781 err = f.args[1].Eval(abuf, ev)
782 if err != nil {
783 return err
784 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900785 t := time.Now()
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900786 ws := newWordScanner(abuf.Bytes())
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900787 for ws.Scan() {
788 name := string(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900789 name, err := filepath.Abs(name)
790 if err != nil {
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900791 logf("abs: %v", err)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900792 continue
793 }
794 name, err = filepath.EvalSymlinks(name)
795 if err != nil {
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900796 logf("realpath: %v", err)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900797 continue
798 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900799 w.writeWordString(name)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900800 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900801 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900802 stats.add("funcbody", "realpath", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900803 return err
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900804}
805
806type funcAbspath struct{ fclosure }
807
808func (f *funcAbspath) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900809func (f *funcAbspath) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900810 err := assertArity("abspath", 1, len(f.args))
811 if err != nil {
812 return err
813 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900814 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900815 err = f.args[1].Eval(abuf, ev)
816 if err != nil {
817 return err
818 }
Fumitoshi Ukai9e0c68d2015-06-19 13:38:19 +0900819 t := time.Now()
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900820 ws := newWordScanner(abuf.Bytes())
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900821 for ws.Scan() {
822 name := string(ws.Bytes())
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900823 name, err := filepath.Abs(name)
824 if err != nil {
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900825 logf("abs: %v", err)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900826 continue
827 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900828 w.writeWordString(name)
Shinichiro Hamajiaf61af22015-04-11 12:13:22 +0900829 }
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +0900830 freeBuf(abuf)
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900831 stats.add("funcbody", "abspath", t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900832 return nil
Shinichiro Hamajic20b84d2015-04-11 12:02:51 +0900833}
834
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900835// http://www.gnu.org/software/make/manual/make.html#Conditional-Functions
836type funcIf struct{ fclosure }
837
838func (f *funcIf) Arity() int { return 3 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900839func (f *funcIf) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900840 err := assertArity("if", 2, len(f.args))
841 if err != nil {
842 return err
843 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900844 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900845 err = f.args[1].Eval(abuf, ev)
846 if err != nil {
847 return err
848 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900849 if len(abuf.Bytes()) != 0 {
850 freeBuf(abuf)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900851 return f.args[2].Eval(w, ev)
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900852 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900853 freeBuf(abuf)
Fumitoshi Ukaie27a25d2015-04-18 00:31:01 +0900854 if len(f.args) > 3 {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900855 return f.args[3].Eval(w, ev)
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900856 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900857 return nil
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900858}
859
860type funcAnd struct{ fclosure }
861
862func (f *funcAnd) Arity() int { return 0 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900863func (f *funcAnd) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900864 err := assertArity("and", 0, len(f.args))
865 if err != nil {
866 return nil
867 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900868 abuf := newBuf()
Shinichiro Hamaji2216dd62015-04-11 13:44:39 +0900869 var cond []byte
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900870 for _, arg := range f.args[1:] {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900871 abuf.Reset()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900872 err = arg.Eval(abuf, ev)
873 if err != nil {
874 return err
875 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900876 cond = abuf.Bytes()
Shinichiro Hamaji2216dd62015-04-11 13:44:39 +0900877 if len(cond) == 0 {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900878 freeBuf(abuf)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900879 return nil
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900880 }
881 }
Shinichiro Hamaji2216dd62015-04-11 13:44:39 +0900882 w.Write(cond)
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900883 freeBuf(abuf)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900884 return nil
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900885}
886
887type funcOr struct{ fclosure }
888
889func (f *funcOr) Arity() int { return 0 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900890func (f *funcOr) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900891 err := assertArity("or", 0, len(f.args))
892 if err != nil {
893 return err
894 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900895 abuf := newBuf()
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900896 for _, arg := range f.args[1:] {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900897 abuf.Reset()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900898 err = arg.Eval(abuf, ev)
899 if err != nil {
900 return err
901 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900902 cond := abuf.Bytes()
Shinichiro Hamaji2216dd62015-04-11 13:44:39 +0900903 if len(cond) != 0 {
904 w.Write(cond)
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900905 freeBuf(abuf)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900906 return nil
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900907 }
908 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900909 freeBuf(abuf)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900910 return nil
Shinichiro Hamaji424baeb2015-04-11 12:35:42 +0900911}
912
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900913// http://www.gnu.org/software/make/manual/make.html#Shell-Function
914type funcShell struct{ fclosure }
915
916func (f *funcShell) Arity() int { return 1 }
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900917
Shinichiro Hamajic0095e32015-05-27 18:49:06 +0900918// A hack for Android build. We need to evaluate things like $((3+4))
919// when we emit ninja file, because the result of such expressions
920// will be passed to other make functions.
921// TODO: Maybe we should modify Android's Makefile and remove this
922// workaround. It would be also nice if we can detect things like
923// this.
924func hasNoIoInShellScript(s []byte) bool {
925 if len(s) == 0 {
926 return true
927 }
928 if !bytes.HasPrefix(s, []byte("echo $((")) || s[len(s)-1] != ')' {
929 return false
930 }
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900931 logf("has no IO - evaluate now: %s", s)
Shinichiro Hamajic0095e32015-05-27 18:49:06 +0900932 return true
933}
934
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900935func (f *funcShell) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900936 err := assertArity("shell", 1, len(f.args))
937 if err != nil {
938 return err
939 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900940 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900941 err = f.args[1].Eval(abuf, ev)
942 if err != nil {
943 return err
944 }
Shinichiro Hamajic0095e32015-05-27 18:49:06 +0900945 if ev.avoidIO && !hasNoIoInShellScript(abuf.Bytes()) {
Fumitoshi Ukai83410132015-06-15 14:50:07 +0900946 te := traceEvent.begin("shell", tmpval(abuf.Bytes()), traceEventMain)
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +0900947 ev.hasIO = true
Fumitoshi Ukai145598a2015-06-19 10:08:17 +0900948 io.WriteString(w, "$(")
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +0900949 w.Write(abuf.Bytes())
Fumitoshi Ukai145598a2015-06-19 10:08:17 +0900950 writeByte(w, ')')
Fumitoshi Ukai432a2422015-06-11 15:16:29 +0900951 traceEvent.end(te)
Fumitoshi Ukai6a643232015-06-08 14:11:23 +0900952 freeBuf(abuf)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900953 return nil
Shinichiro Hamaji8b6487f2015-05-26 16:21:47 +0900954 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900955 arg := abuf.String()
956 freeBuf(abuf)
Shinichiro Hamaji89551c92015-04-11 19:33:03 +0900957 shellVar := ev.LookupVar("SHELL")
958 // TODO: Should be Eval, not String.
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900959 cmdline := []string{shellVar.String(), "-c", arg}
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900960 if LogFlag {
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900961 logf("shell %q", cmdline)
Fumitoshi Ukai44ae8cf2015-06-24 16:44:15 +0900962 }
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900963 cmd := exec.Cmd{
964 Path: cmdline[0],
965 Args: cmdline,
966 Stderr: os.Stderr,
967 }
Fumitoshi Ukai83410132015-06-15 14:50:07 +0900968 te := traceEvent.begin("shell", literal(arg), traceEventMain)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900969 out, err := cmd.Output()
Fumitoshi Ukai9042b992015-06-23 16:10:27 +0900970 shellStats.add(time.Since(te.t))
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900971 if err != nil {
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900972 logf("$(shell %q) failed: %q", arg, err)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900973 }
Shinichiro Hamajiba6b84d2015-06-03 18:46:13 +0900974 w.Write(formatCommandOutput(out))
Fumitoshi Ukai432a2422015-06-11 15:16:29 +0900975 traceEvent.end(te)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900976 return nil
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900977}
978
Fumitoshi Ukai106fb792015-06-09 10:37:35 +0900979func (f *funcShell) Compact() Value {
980 if len(f.args)-1 < 1 {
981 return f
982 }
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900983 if !UseFindCache && !UseShellBuiltins {
Fumitoshi Ukai106fb792015-06-09 10:37:35 +0900984 return f
985 }
986
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900987 var exp expr
Fumitoshi Ukai44ae8cf2015-06-24 16:44:15 +0900988 switch v := f.args[1].(type) {
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900989 case expr:
990 exp = v
Fumitoshi Ukai44ae8cf2015-06-24 16:44:15 +0900991 default:
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900992 exp = expr{v}
Fumitoshi Ukai106fb792015-06-09 10:37:35 +0900993 }
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900994 if UseShellBuiltins {
Fumitoshi Ukai4a708512015-06-11 17:15:49 +0900995 // hack for android
996 for _, sb := range shBuiltins {
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900997 if v, ok := matchExpr(exp, sb.pattern); ok {
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900998 logf("shell compact apply %s for %s", sb.name, exp)
Fumitoshi Ukai4a708512015-06-11 17:15:49 +0900999 return sb.compact(f, v)
1000 }
Fumitoshi Ukai76b609e2015-06-10 14:56:49 +09001001 }
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +09001002 logf("shell compact no match: %s", exp)
Fumitoshi Ukai76b609e2015-06-10 14:56:49 +09001003 }
Fumitoshi Ukai106fb792015-06-09 10:37:35 +09001004 return f
1005}
1006
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001007// https://www.gnu.org/software/make/manual/html_node/Call-Function.html#Call-Function
1008type funcCall struct{ fclosure }
1009
1010func (f *funcCall) Arity() int { return 0 }
1011
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001012func (f *funcCall) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001013 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001014 fargs, err := ev.args(abuf, f.args[1:]...)
1015 if err != nil {
1016 return err
1017 }
Fumitoshi Ukaif543f4d2015-06-15 15:21:47 +09001018 varname := fargs[0]
1019 variable := string(varname)
Fumitoshi Ukai83410132015-06-15 14:50:07 +09001020 te := traceEvent.begin("call", literal(variable), traceEventMain)
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +09001021 if LogFlag {
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +09001022 logf("call %q variable %q", f.args[1], variable)
Fumitoshi Ukai5c04ad82015-06-18 16:14:04 +09001023 }
Fumitoshi Ukaif543f4d2015-06-15 15:21:47 +09001024 v := ev.LookupVar(variable)
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001025 // Evalualte all arguments first before we modify the table.
Shinichiro Hamaji39728f12015-04-11 20:12:23 +09001026 var args []tmpval
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +09001027 // $0 is variable.
Fumitoshi Ukaif543f4d2015-06-15 15:21:47 +09001028 args = append(args, tmpval(varname))
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +09001029 // TODO(ukai): If variable is the name of a built-in function,
1030 // the built-in function is always invoked (even if a make variable
1031 // by that name also exists).
1032
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001033 for i, arg := range fargs[1:] {
1034 // f.args[2]=>args[1] will be $1.
1035 args = append(args, tmpval(arg))
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +09001036 if LogFlag {
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +09001037 logf("call $%d: %q=>%q", i+1, arg, fargs[i+1])
Fumitoshi Ukai5c04ad82015-06-18 16:14:04 +09001038 }
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001039 }
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +09001040 oldParams := ev.paramVars
1041 ev.paramVars = args
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001042
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001043 var buf bytes.Buffer
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +09001044 if LogFlag {
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001045 w = &ssvWriter{Writer: io.MultiWriter(w, &buf)}
Fumitoshi Ukaie27a25d2015-04-18 00:31:01 +09001046 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001047 err = v.Eval(w, ev)
1048 if err != nil {
1049 return err
1050 }
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +09001051 ev.paramVars = oldParams
Fumitoshi Ukai72598e72015-06-11 15:53:09 +09001052 traceEvent.end(te)
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +09001053 if LogFlag {
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +09001054 logf("call %q variable %q return %q", f.args[1], variable, buf.Bytes())
Fumitoshi Ukai5c04ad82015-06-18 16:14:04 +09001055 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001056 freeBuf(abuf)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001057 return nil
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001058}
1059
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +09001060// http://www.gnu.org/software/make/manual/make.html#Value-Function
1061type funcValue struct{ fclosure }
1062
1063func (f *funcValue) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001064func (f *funcValue) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001065 err := assertArity("value", 1, len(f.args))
1066 if err != nil {
1067 return err
1068 }
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +09001069 abuf := newBuf()
1070 err = f.args[1].Eval(abuf, ev)
1071 if err != nil {
1072 return err
1073 }
1074 v := ev.LookupVar(abuf.String())
1075 freeBuf(abuf)
Fumitoshi Ukai145598a2015-06-19 10:08:17 +09001076 io.WriteString(w, v.String())
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001077 return nil
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +09001078}
1079
1080// http://www.gnu.org/software/make/manual/make.html#Eval-Function
1081type funcEval struct{ fclosure }
1082
1083func (f *funcEval) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001084func (f *funcEval) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001085 err := assertArity("eval", 1, len(f.args))
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +09001086 if err != nil {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001087 return err
1088 }
1089 abuf := newBuf()
1090 err = f.args[1].Eval(abuf, ev)
1091 if err != nil {
1092 return err
1093 }
1094 s := abuf.Bytes()
1095 logf("eval %q at %s", s, ev.srcpos)
1096 mk, err := parseMakefileBytes(s, ev.srcpos)
1097 if err != nil {
1098 return ev.errorf("%v", err)
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +09001099 }
1100
1101 for _, stmt := range mk.stmts {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001102 err = ev.eval(stmt)
1103 if err != nil {
1104 return err
1105 }
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +09001106 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001107 freeBuf(abuf)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001108 return nil
Shinichiro Hamaji28ea5bc2015-04-11 12:41:08 +09001109}
1110
Fumitoshi Ukai9f6b6352015-04-16 16:25:09 +09001111func (f *funcEval) Compact() Value {
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +09001112 if len(f.args)-1 < 1 {
1113 return f
1114 }
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +09001115 switch arg := f.args[1].(type) {
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +09001116 case literal, tmpval:
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +09001117 case expr:
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +09001118 if len(arg) == 1 {
1119 return f
1120 }
1121 switch prefix := arg[0].(type) {
1122 case literal, tmpval:
1123 lhs, op, rhsprefix, ok := parseAssignLiteral(prefix.String())
1124 if ok {
1125 // $(eval foo = $(bar))
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +09001126 var rhs expr
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +09001127 if rhsprefix != literal("") {
1128 rhs = append(rhs, rhsprefix)
1129 }
1130 rhs = append(rhs, arg[1:]...)
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +09001131 logf("eval assign %#v => lhs:%q op:%q rhs:%#v", f, lhs, op, rhs)
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +09001132 return &funcEvalAssign{
1133 lhs: lhs,
1134 op: op,
1135 rhs: compactExpr(rhs),
1136 }
1137 }
1138 }
1139 // TODO(ukai): eval -> varassign. e.g $(eval $(foo) := $(x)).
Fumitoshi Ukai769157a2015-06-02 15:18:53 +09001140 return f
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +09001141 default:
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +09001142 return f
1143 }
1144 arg := f.args[1].String()
1145 arg = stripComment(arg)
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +09001146 if arg == "" || strings.TrimSpace(arg) == "" {
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +09001147 return &funcNop{expr: f.String()}
1148 }
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +09001149 f.args[1] = literal(arg)
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +09001150 lhs, op, rhs, ok := parseAssignLiteral(f.args[1].String())
1151 if ok {
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001152 return &funcEvalAssign{
1153 lhs: lhs,
1154 op: op,
1155 rhs: rhs,
1156 }
1157 }
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +09001158 return f
1159}
1160
1161func stripComment(arg string) string {
1162 for {
1163 i := strings.Index(arg, "#")
1164 if i < 0 {
1165 return arg
1166 }
1167 eol := strings.Index(arg[i:], "\n")
1168 if eol < 0 {
1169 return arg[:i]
1170 }
1171 arg = arg[:i] + arg[eol+1:]
1172 }
1173}
1174
1175type funcNop struct{ expr string }
1176
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001177func (f *funcNop) String() string { return f.expr }
1178func (f *funcNop) Eval(evalWriter, *Evaluator) error { return nil }
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +09001179func (f *funcNop) serialize() serializableVar {
1180 return serializableVar{
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +09001181 Type: "funcNop",
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001182 V: f.expr,
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +09001183 }
1184}
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001185func (f *funcNop) dump(d *dumpbuf) {
1186 d.Byte(valueTypeNop)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +09001187}
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +09001188
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +09001189func parseAssignLiteral(s string) (lhs, op string, rhs Value, ok bool) {
1190 eq := strings.Index(s, "=")
1191 if eq < 0 {
1192 return "", "", nil, false
1193 }
1194 // TODO(ukai): factor out parse assign?
1195 lhs = s[:eq]
1196 op = s[eq : eq+1]
1197 if eq >= 1 && (s[eq-1] == ':' || s[eq-1] == '+' || s[eq-1] == '?') {
1198 lhs = s[:eq-1]
1199 op = s[eq-1 : eq+1]
1200 }
1201 lhs = strings.TrimSpace(lhs)
1202 if strings.IndexAny(lhs, ":$") >= 0 {
1203 // target specific var, or need eval.
1204 return "", "", nil, false
1205 }
1206 r := strings.TrimLeft(s[eq+1:], " \t")
1207 rhs = literal(r)
1208 return lhs, op, rhs, true
1209}
1210
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001211type funcEvalAssign struct {
1212 lhs string
1213 op string
1214 rhs Value
1215}
1216
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001217func (f *funcEvalAssign) String() string {
1218 return fmt.Sprintf("$(eval %s %s %s)", f.lhs, f.op, f.rhs)
1219}
1220
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001221func (f *funcEvalAssign) Eval(w evalWriter, ev *Evaluator) error {
1222 var abuf buffer
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001223 err := f.rhs.Eval(&abuf, ev)
1224 if err != nil {
1225 return err
1226 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001227 rhs := trimLeftSpaceBytes(abuf.Bytes())
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001228 var rvalue Var
1229 switch f.op {
1230 case ":=":
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +09001231 // TODO(ukai): compute parsed expr in Compact when f.rhs is
1232 // literal? e.g. literal("$(foo)") => varref{literal("foo")}.
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +09001233 exp, _, err := parseExpr(rhs, nil, parseOp{})
Fumitoshi Ukaifa5e9222015-04-17 11:45:20 +09001234 if err != nil {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001235 return ev.errorf("eval assign error: %q: %v", f.String(), err)
Fumitoshi Ukaifa5e9222015-04-17 11:45:20 +09001236 }
Fumitoshi Ukaidd248f22015-06-18 23:04:28 +09001237 vbuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001238 err = exp.Eval(vbuf, ev)
1239 if err != nil {
1240 return err
1241 }
Fumitoshi Ukai7bf992d2015-06-25 12:42:19 +09001242 rvalue = &simpleVar{value: vbuf.String(), origin: "file"}
Fumitoshi Ukaidd248f22015-06-18 23:04:28 +09001243 freeBuf(vbuf)
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001244 case "=":
Fumitoshi Ukai7bf992d2015-06-25 12:42:19 +09001245 rvalue = &recursiveVar{expr: tmpval(rhs), origin: "file"}
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001246 case "+=":
1247 prev := ev.LookupVar(f.lhs)
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +09001248 if prev.IsDefined() {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001249 rvalue, err = prev.Append(ev, string(rhs))
1250 if err != nil {
1251 return err
1252 }
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001253 } else {
Fumitoshi Ukai7bf992d2015-06-25 12:42:19 +09001254 rvalue = &recursiveVar{expr: tmpval(rhs), origin: "file"}
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001255 }
1256 case "?=":
1257 prev := ev.LookupVar(f.lhs)
1258 if prev.IsDefined() {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001259 return nil
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001260 }
Fumitoshi Ukai7bf992d2015-06-25 12:42:19 +09001261 rvalue = &recursiveVar{expr: tmpval(rhs), origin: "file"}
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001262 }
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +09001263 if LogFlag {
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +09001264 logf("Eval ASSIGN: %s=%q (flavor:%q)", f.lhs, rvalue, rvalue.Flavor())
Fumitoshi Ukai5c04ad82015-06-18 16:14:04 +09001265 }
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001266 ev.outVars.Assign(f.lhs, rvalue)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001267 return nil
Fumitoshi Ukai150c8612015-04-16 15:35:44 +09001268}
1269
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +09001270func (f *funcEvalAssign) serialize() serializableVar {
1271 return serializableVar{
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +09001272 Type: "funcEvalAssign",
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +09001273 Children: []serializableVar{
1274 serializableVar{V: f.lhs},
1275 serializableVar{V: f.op},
1276 f.rhs.serialize(),
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +09001277 },
1278 }
1279}
1280
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001281func (f *funcEvalAssign) dump(d *dumpbuf) {
1282 d.Byte(valueTypeAssign)
1283 d.Str(f.lhs)
1284 d.Str(f.op)
1285 f.rhs.dump(d)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +09001286}
1287
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001288// http://www.gnu.org/software/make/manual/make.html#Origin-Function
1289type funcOrigin struct{ fclosure }
1290
1291func (f *funcOrigin) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001292func (f *funcOrigin) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001293 err := assertArity("origin", 1, len(f.args))
1294 if err != nil {
1295 return err
1296 }
Fumitoshi Ukaib64400e2015-06-30 16:06:09 +09001297 abuf := newBuf()
1298 err = f.args[1].Eval(abuf, ev)
1299 if err != nil {
1300 return err
1301 }
1302 v := ev.LookupVar(abuf.String())
1303 freeBuf(abuf)
Fumitoshi Ukai145598a2015-06-19 10:08:17 +09001304 io.WriteString(w, v.Origin())
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001305 return nil
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001306}
1307
1308// https://www.gnu.org/software/make/manual/html_node/Flavor-Function.html#Flavor-Function
1309type funcFlavor struct{ fclosure }
1310
1311func (f *funcFlavor) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001312func (f *funcFlavor) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001313 err := assertArity("flavor", 1, len(f.args))
1314 if err != nil {
1315 return err
1316 }
Fumitoshi Ukaib64400e2015-06-30 16:06:09 +09001317 abuf := newBuf()
1318 err = f.args[1].Eval(abuf, ev)
1319 if err != nil {
1320 return err
1321 }
1322 v := ev.LookupVar(abuf.String())
1323 freeBuf(abuf)
Fumitoshi Ukai145598a2015-06-19 10:08:17 +09001324 io.WriteString(w, v.Flavor())
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001325 return nil
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001326}
1327
1328// http://www.gnu.org/software/make/manual/make.html#Make-Control-Functions
1329type funcInfo struct{ fclosure }
1330
1331func (f *funcInfo) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001332func (f *funcInfo) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001333 err := assertArity("info", 1, len(f.args))
1334 if err != nil {
1335 return err
1336 }
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001337 if ev.avoidIO {
Fumitoshi Ukai145598a2015-06-19 10:08:17 +09001338 io.WriteString(w, "KATI_TODO(info)")
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001339 ev.hasIO = true
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001340 return nil
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001341 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001342 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001343 err = f.args[1].Eval(abuf, ev)
1344 if err != nil {
1345 return err
1346 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001347 fmt.Printf("%s\n", abuf.String())
1348 freeBuf(abuf)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001349 return nil
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001350}
1351
1352type funcWarning struct{ fclosure }
1353
1354func (f *funcWarning) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001355func (f *funcWarning) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001356 err := assertArity("warning", 1, len(f.args))
1357 if err != nil {
1358 return err
1359 }
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001360 if ev.avoidIO {
Fumitoshi Ukai145598a2015-06-19 10:08:17 +09001361 io.WriteString(w, "KATI_TODO(warning)")
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001362 ev.hasIO = true
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001363 return nil
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001364 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001365 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001366 err = f.args[1].Eval(abuf, ev)
1367 if err != nil {
1368 return err
1369 }
1370 fmt.Printf("%s: %s\n", ev.srcpos, abuf.String())
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001371 freeBuf(abuf)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001372 return nil
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001373}
1374
1375type funcError struct{ fclosure }
1376
1377func (f *funcError) Arity() int { return 1 }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001378func (f *funcError) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001379 err := assertArity("error", 1, len(f.args))
1380 if err != nil {
1381 return err
1382 }
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001383 if ev.avoidIO {
Fumitoshi Ukai145598a2015-06-19 10:08:17 +09001384 io.WriteString(w, "KATI_TODO(error)")
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001385 ev.hasIO = true
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001386 return nil
Shinichiro Hamajib41fd502015-04-29 03:34:07 +09001387 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001388 var abuf buffer
1389 err = f.args[1].Eval(&abuf, ev)
1390 if err != nil {
1391 return err
1392 }
1393 return ev.errorf("*** %s.", abuf.String())
Shinichiro Hamaji916f35f2015-04-11 12:46:19 +09001394}
1395
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001396// http://www.gnu.org/software/make/manual/make.html#Foreach-Function
1397type funcForeach struct{ fclosure }
1398
1399func (f *funcForeach) Arity() int { return 3 }
1400
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +09001401func (f *funcForeach) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001402 err := assertArity("foreach", 3, len(f.args))
1403 if err != nil {
1404 return err
1405 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001406 abuf := newBuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001407 fargs, err := ev.args(abuf, f.args[1], f.args[2])
1408 if err != nil {
1409 return err
1410 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001411 varname := string(fargs[0])
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +09001412 ws := newWordScanner(fargs[1])
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +09001413 text := f.args[3]
Fumitoshi Ukai21426172015-06-30 18:02:45 +09001414 ov := ev.LookupVar(varname)
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001415 space := false
Fumitoshi Ukai9da19f62015-05-08 14:39:08 +09001416 for ws.Scan() {
1417 word := ws.Bytes()
Fumitoshi Ukai7bf992d2015-06-25 12:42:19 +09001418 ev.outVars.Assign(varname, &automaticVar{value: word})
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001419 if space {
Fumitoshi Ukai145598a2015-06-19 10:08:17 +09001420 writeByte(w, ' ')
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001421 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001422 err = text.Eval(w, ev)
1423 if err != nil {
1424 return err
1425 }
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001426 space = true
1427 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +09001428 freeBuf(abuf)
Fumitoshi Ukai21426172015-06-30 18:02:45 +09001429 av := ev.LookupVar(varname)
1430 if _, ok := av.(*automaticVar); ok {
1431 ev.outVars.Assign(varname, ov)
1432 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +09001433 return nil
Fumitoshi Ukaid2bcf662015-04-11 01:02:27 +09001434}