aboutsummaryrefslogtreecommitdiff
path: root/golang/kati/evalcmd.go
diff options
context:
space:
mode:
Diffstat (limited to 'golang/kati/evalcmd.go')
-rw-r--r--golang/kati/evalcmd.go369
1 files changed, 0 insertions, 369 deletions
diff --git a/golang/kati/evalcmd.go b/golang/kati/evalcmd.go
deleted file mode 100644
index 37f94b8..0000000
--- a/golang/kati/evalcmd.go
+++ /dev/null
@@ -1,369 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package kati
-
-import (
- "fmt"
- "os/exec"
- "strings"
- "sync"
-
- "github.com/golang/glog"
-)
-
-type execContext struct {
- shell string
-
- mu sync.Mutex
- ev *Evaluator
- vpaths searchPaths
- output string
- inputs []string
-}
-
-func newExecContext(vars Vars, vpaths searchPaths, avoidIO bool) *execContext {
- ev := NewEvaluator(vars)
- ev.avoidIO = avoidIO
-
- ctx := &execContext{
- ev: ev,
- vpaths: vpaths,
- }
- av := autoVar{ctx: ctx}
- for k, v := range map[string]Var{
- "@": autoAtVar{autoVar: av},
- "<": autoLessVar{autoVar: av},
- "^": autoHatVar{autoVar: av},
- "+": autoPlusVar{autoVar: av},
- "*": autoStarVar{autoVar: av},
- } {
- ev.vars[k] = v
- // $<k>D = $(patsubst %/,%,$(dir $<k>))
- ev.vars[k+"D"] = suffixDVar(k)
- // $<k>F = $(notdir $<k>)
- ev.vars[k+"F"] = suffixFVar(k)
- }
-
- // TODO: We should move this to somewhere around evalCmd so that
- // we can handle SHELL in target specific variables.
- shell, err := ev.EvaluateVar("SHELL")
- if err != nil {
- shell = "/bin/sh"
- }
- ctx.shell = shell
- return ctx
-}
-
-func (ec *execContext) uniqueInputs() []string {
- var uniqueInputs []string
- seen := make(map[string]bool)
- for _, input := range ec.inputs {
- if !seen[input] {
- seen[input] = true
- uniqueInputs = append(uniqueInputs, input)
- }
- }
- return uniqueInputs
-}
-
-type autoVar struct{ ctx *execContext }
-
-func (v autoVar) Flavor() string { return "undefined" }
-func (v autoVar) Origin() string { return "automatic" }
-func (v autoVar) IsDefined() bool { return true }
-func (v autoVar) Append(*Evaluator, string) (Var, error) {
- return nil, fmt.Errorf("cannot append to autovar")
-}
-func (v autoVar) AppendVar(*Evaluator, Value) (Var, error) {
- return nil, fmt.Errorf("cannot append to autovar")
-}
-func (v autoVar) serialize() serializableVar {
- return serializableVar{Type: ""}
-}
-func (v autoVar) dump(d *dumpbuf) {
- d.err = fmt.Errorf("cannot dump auto var: %v", v)
-}
-
-type autoAtVar struct{ autoVar }
-
-func (v autoAtVar) Eval(w evalWriter, ev *Evaluator) error {
- fmt.Fprint(w, v.String())
- return nil
-}
-func (v autoAtVar) String() string { return v.ctx.output }
-
-type autoLessVar struct{ autoVar }
-
-func (v autoLessVar) Eval(w evalWriter, ev *Evaluator) error {
- fmt.Fprint(w, v.String())
- return nil
-}
-func (v autoLessVar) String() string {
- if len(v.ctx.inputs) > 0 {
- return v.ctx.inputs[0]
- }
- return ""
-}
-
-type autoHatVar struct{ autoVar }
-
-func (v autoHatVar) Eval(w evalWriter, ev *Evaluator) error {
- fmt.Fprint(w, v.String())
- return nil
-}
-func (v autoHatVar) String() string {
- return strings.Join(v.ctx.uniqueInputs(), " ")
-}
-
-type autoPlusVar struct{ autoVar }
-
-func (v autoPlusVar) Eval(w evalWriter, ev *Evaluator) error {
- fmt.Fprint(w, v.String())
- return nil
-}
-func (v autoPlusVar) String() string { return strings.Join(v.ctx.inputs, " ") }
-
-type autoStarVar struct{ autoVar }
-
-func (v autoStarVar) Eval(w evalWriter, ev *Evaluator) error {
- fmt.Fprint(w, v.String())
- return nil
-}
-
-// TODO: Use currentStem. See auto_stem_var.mk
-func (v autoStarVar) String() string { return stripExt(v.ctx.output) }
-
-func suffixDVar(k string) Var {
- return &recursiveVar{
- expr: expr{
- &funcPatsubst{
- fclosure: fclosure{
- args: []Value{
- literal("(patsubst"),
- literal("%/"),
- literal("%"),
- &funcDir{
- fclosure: fclosure{
- args: []Value{
- literal("(dir"),
- &varref{
- varname: literal(k),
- },
- },
- },
- },
- },
- },
- },
- },
- origin: "automatic",
- }
-}
-
-func suffixFVar(k string) Var {
- return &recursiveVar{
- expr: expr{
- &funcNotdir{
- fclosure: fclosure{
- args: []Value{
- literal("(notdir"),
- &varref{varname: literal(k)},
- },
- },
- },
- },
- origin: "automatic",
- }
-}
-
-// runner is a single shell command invocation.
-type runner struct {
- output string
- cmd string
- echo bool
- ignoreError bool
- shell string
-}
-
-func (r runner) String() string {
- cmd := r.cmd
- if !r.echo {
- cmd = "@" + cmd
- }
- if r.ignoreError {
- cmd = "-" + cmd
- }
- return cmd
-}
-
-func (r runner) forCmd(s string) runner {
- for {
- s = trimLeftSpace(s)
- if s == "" {
- return runner{}
- }
- switch s[0] {
- case '@':
- if !DryRunFlag {
- r.echo = false
- }
- s = s[1:]
- continue
- case '-':
- r.ignoreError = true
- s = s[1:]
- continue
- }
- break
- }
- r.cmd = s
- return r
-}
-
-func (r runner) eval(ev *Evaluator, s string) ([]runner, error) {
- r = r.forCmd(s)
- if strings.IndexByte(r.cmd, '$') < 0 {
- // fast path
- return []runner{r}, nil
- }
- // TODO(ukai): parse once more earlier?
- expr, _, err := parseExpr([]byte(r.cmd), nil, parseOp{})
- if err != nil {
- return nil, ev.errorf("parse cmd %q: %v", r.cmd, err)
- }
- buf := newEbuf()
- err = expr.Eval(buf, ev)
- if err != nil {
- return nil, err
- }
- cmds := buf.String()
- buf.release()
- glog.V(1).Infof("evalcmd: %q => %q", r.cmd, cmds)
- var runners []runner
- for _, cmd := range strings.Split(cmds, "\n") {
- if len(runners) > 0 && strings.HasSuffix(runners[len(runners)-1].cmd, "\\") {
- runners[len(runners)-1].cmd += "\n"
- runners[len(runners)-1].cmd += cmd
- continue
- }
- runners = append(runners, r.forCmd(cmd))
- }
- return runners, nil
-}
-
-func (r runner) run(output string) error {
- if r.echo || DryRunFlag {
- fmt.Printf("%s\n", r.cmd)
- }
- s := cmdline(r.cmd)
- glog.Infof("sh:%q", s)
- if DryRunFlag {
- return nil
- }
- args := []string{r.shell, "-c", s}
- cmd := exec.Cmd{
- Path: args[0],
- Args: args,
- }
- out, err := cmd.CombinedOutput()
- fmt.Printf("%s", out)
- exit := exitStatus(err)
- if r.ignoreError && exit != 0 {
- fmt.Printf("[%s] Error %d (ignored)\n", output, exit)
- err = nil
- }
- return err
-}
-
-func createRunners(ctx *execContext, n *DepNode) ([]runner, bool, error) {
- var runners []runner
- if len(n.Cmds) == 0 {
- return runners, false, nil
- }
-
- ctx.mu.Lock()
- defer ctx.mu.Unlock()
- // For automatic variables.
- ctx.output = n.Output
- ctx.inputs = n.ActualInputs
- for k, v := range n.TargetSpecificVars {
- restore := ctx.ev.vars.save(k)
- defer restore()
- ctx.ev.vars[k] = v
- if glog.V(1) {
- glog.Infof("set tsv: %s=%s", k, v)
- }
- }
-
- ctx.ev.filename = n.Filename
- ctx.ev.lineno = n.Lineno
- glog.Infof("Building: %s cmds:%q", n.Output, n.Cmds)
- r := runner{
- output: n.Output,
- echo: true,
- shell: ctx.shell,
- }
- for _, cmd := range n.Cmds {
- rr, err := r.eval(ctx.ev, cmd)
- if err != nil {
- return nil, false, err
- }
- for _, r := range rr {
- if len(r.cmd) != 0 {
- runners = append(runners, r)
- }
- }
- }
- if len(ctx.ev.delayedOutputs) > 0 {
- var nrunners []runner
- r := runner{
- output: n.Output,
- shell: ctx.shell,
- }
- for _, o := range ctx.ev.delayedOutputs {
- nrunners = append(nrunners, r.forCmd(o))
- }
- nrunners = append(nrunners, runners...)
- runners = nrunners
- ctx.ev.delayedOutputs = nil
- }
- return runners, ctx.ev.hasIO, nil
-}
-
-func evalCommands(nodes []*DepNode, vars Vars) error {
- ioCnt := 0
- ectx := newExecContext(vars, searchPaths{}, true)
- for i, n := range nodes {
- runners, hasIO, err := createRunners(ectx, n)
- if err != nil {
- return err
- }
- if hasIO {
- ioCnt++
- if ioCnt%100 == 0 {
- logStats("%d/%d rules have IO", ioCnt, i+1)
- }
- continue
- }
-
- n.Cmds = []string{}
- n.TargetSpecificVars = make(Vars)
- for _, r := range runners {
- n.Cmds = append(n.Cmds, r.String())
- }
- }
- logStats("%d/%d rules have IO", ioCnt, len(nodes))
- return nil
-}