diff --git a/expand.go b/expand.go index 4ef896c..7fc7d83 100644 --- a/expand.go +++ b/expand.go @@ -5,6 +5,7 @@ package main import ( "regexp" "strings" + "os" "unicode/utf8" ) @@ -89,31 +90,35 @@ func expandEscape(input string) (string, int) { if c == '\t' || c == ' ' { return string(c), w } + if c == '\n' { + return "", w + } return "\\" + string(c), w } // Expand a double quoted string starting after a '\"' func expandDoubleQuoted(input string, vars map[string][]string, expandBackticks bool) (string, int) { // find the first non-escaped " + i := 0 j := 0 for { - j = strings.IndexAny(input[j:], "\"\\") + j = strings.IndexAny(input[i:], "\"\\") if j < 0 { break } + j += i c, w := utf8.DecodeRuneInString(input[j:]) - j += w + i = j + w if c == '"' { - return strings.Join(expand(input[:j], vars, expandBackticks), " "), (j + w) + return strings.Join(expand(input[:j], vars, expandBackticks), " "), i } if c == '\\' { - if j+w < len(input) { - j += w - _, w := utf8.DecodeRuneInString(input[j:]) - j += w + if i < len(input) { + _, w := utf8.DecodeRuneInString(input[i:]) + i += w } else { break } @@ -303,9 +308,14 @@ func expandBackQuoted(input string, vars map[string][]string) ([]string, int) { if j < 0 { return []string{input}, len(input) } + + env := os.Environ() + for key, values := range vars { + env = append(env, key + "=" + strings.Join(values, " ")) + } // TODO: handle errors - output, _ := subprocess("sh", nil, input[:j], true) + output, _ := subprocess("sh", nil, env, input[:j], true) parts := make([]string, 0) _, tokens := lexWords(output) diff --git a/mk.go b/mk.go index 915429a..3079012 100644 --- a/mk.go +++ b/mk.go @@ -24,7 +24,9 @@ var rebuildtargets map[string]bool = make(map[string]bool) var mkMsgMutex sync.Mutex // The maximum number of times an rule may be applied. -const maxRuleCnt = 1 +// This limits recursion of both meta- and non-meta-rules! +// Maybe, this shouldn't affect meta-rules?! +var maxRuleCnt int = 1 // Limit the number of recipes executed simultaneously. var subprocsAllowed int @@ -312,6 +314,7 @@ func main() { flag.BoolVar(&shallowrebuild, "r", false, "force building of just targets") flag.BoolVar(&rebuildall, "a", false, "force building of all dependencies") flag.IntVar(&subprocsAllowed, "p", 4, "maximum number of jobs to execute in parallel") + flag.IntVar(&maxRuleCnt, "l", 1, "maximum number of times a specific rule can be applied (recursion)") flag.BoolVar(&interactive, "i", false, "prompt before executing rules") flag.BoolVar(&quiet, "q", false, "don't print recipes before executing them") flag.Parse() diff --git a/parse.go b/parse.go index 4e76540..09b48b7 100644 --- a/parse.go +++ b/parse.go @@ -118,7 +118,7 @@ func parsePipeInclude(p *parser, t token) parserStateFun { args[i] = p.tokenbuf[i].val } - output, success := subprocess("sh", args, "", true) + output, success := subprocess("sh", args, nil, "", true) if !success { p.basicErrorAtToken("subprocess include failed", t) } diff --git a/recipe.go b/recipe.go index 27d9a31..fccaa53 100644 --- a/recipe.go +++ b/recipe.go @@ -106,6 +106,7 @@ func dorecipe(target string, u *node, e *edge, dryrun bool) bool { _, success := subprocess( sh, args, + nil, input, false) @@ -127,6 +128,7 @@ func dorecipe(target string, u *node, e *edge, dryrun bool) bool { // func subprocess(program string, args []string, + env []string, input string, capture_out bool) (string, bool) { program_path, err := exec.LookPath(program) @@ -142,7 +144,7 @@ func subprocess(program string, log.Fatal(err) } - attr := os.ProcAttr{Files: []*os.File{stdin_pipe_read, os.Stdout, os.Stderr}} + attr := os.ProcAttr{Env: env, Files: []*os.File{stdin_pipe_read, os.Stdout, os.Stderr}} output := make([]byte, 0) capture_done := make(chan bool)