blob: 5b46fa17b5349bcfe799760455a5219d63c69488 [file] [log] [blame]
package main
import (
"fmt"
"os/exec"
"path/filepath"
"regexp"
"strings"
)
// Func is a make function.
// http://www.gnu.org/software/make/manual/make.html#Functions
// TODO(ukai): return error instead of panic?
// TODO(ukai): each func has nargs, and don't split , more than narg?
type Func func(*Evaluator, []string) string
func funcSubst(ev *Evaluator, args []string) string {
Log("subst %q", args)
if len(args) < 3 {
panic(fmt.Sprintf("*** insufficient number of arguments (%d) to function `subst'.", len(args)))
}
from := ev.evalExpr(args[0])
to := ev.evalExpr(args[1])
text := ev.evalExpr(strings.Join(args[2:], ","))
return strings.Replace(text, from, to, -1)
}
func funcPatsubst(ev *Evaluator, args []string) string {
Log("patsubst %q", args)
if len(args) < 3 {
panic(fmt.Sprintf("*** insufficient number of arguments (%d) to function `patsubst'.", len(args)))
}
pat := ev.evalExpr(args[0])
repl := ev.evalExpr(args[1])
texts := splitSpaces(ev.evalExpr(strings.Join(args[2:], ",")))
for i, text := range texts {
texts[i] = substPattern(pat, repl, text)
}
return strings.Join(texts, " ")
}
// http://www.gnu.org/software/make/manual/make.html#File-Name-Functions
func funcWildcard(ev *Evaluator, args []string) string {
Log("wildcard %q", args)
pattern := ev.evalExpr(strings.Join(args, ","))
files, err := filepath.Glob(pattern)
if err != nil {
panic(err)
}
return strings.Join(files, " ")
}
func funcRealpath(ev *Evaluator, args []string) string {
Log("realpath %q", args)
names := strings.Split(ev.evalExpr(strings.Join(args, ",")), " \t")
var realpaths []string
for _, name := range names {
name = strings.TrimSpace(name)
name, err := filepath.Abs(name)
if err != nil {
Log("abs: %v", err)
continue
}
name, err = filepath.EvalSymlinks(name)
if err != nil {
Log("realpath: %v", err)
continue
}
realpaths = append(realpaths, name)
}
return strings.Join(realpaths, " ")
}
func funcAbspath(ev *Evaluator, args []string) string {
Log("abspath %q", args)
names := strings.Split(ev.evalExpr(strings.Join(args, ",")), " \t")
var realpaths []string
for _, name := range names {
name = strings.TrimSpace(name)
name, err := filepath.Abs(name)
if err != nil {
Log("abs: %v", err)
continue
}
realpaths = append(realpaths, name)
}
return strings.Join(realpaths, " ")
}
// http://www.gnu.org/software/make/manual/make.html#Shell-Function
func funcShell(ev *Evaluator, args []string) string {
Log("shell %q", args)
arg := ev.evalExpr(strings.Join(args, ","))
cmdline := []string{"/bin/sh", "-c", arg}
cmd := exec.Cmd{
Path: cmdline[0],
Args: cmdline,
}
out, err := cmd.CombinedOutput()
if err != nil {
panic(err)
}
re, err := regexp.Compile(`\s`)
if err != nil {
panic(err)
}
return string(re.ReplaceAllString(string(out), " "))
}
// http://www.gnu.org/software/make/manual/make.html#Make-Control-Functions
func funcWarning(ev *Evaluator, args []string) string {
Log("warning %q", args)
arg := ev.evalExpr(strings.Join(args, ","))
fmt.Printf("%s:%d: %s\n", ev.filename, ev.lineno, arg)
return ""
}