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