fix panic based error reporting
diff --git a/ninja.go b/ninja.go
index 5f6c648..9acf664 100644
--- a/ninja.go
+++ b/ninja.go
@@ -33,21 +33,17 @@
 	ex      *Executor
 	ruleID  int
 	done    map[string]bool
-	ccRe    *regexp.Regexp
 	gomaDir string
 }
 
+var ccRE = regexp.MustCompile(`^prebuilts/(gcc|clang)/.*(gcc|g\+\+|clang|clang\+\+) .* -c `)
+
 func newNinjaGenerator(g *DepGraph, gomaDir string) *ninjaGenerator {
-	ccRe, err := regexp.Compile(`^prebuilts/(gcc|clang)/.*(gcc|g\+\+|clang|clang\+\+) .* -c `)
-	if err != nil {
-		panic(err)
-	}
 	return &ninjaGenerator{
 		nodes:   g.nodes,
 		vars:    g.vars,
 		exports: g.exports,
 		done:    make(map[string]bool),
-		ccRe:    ccRe,
 		gomaDir: gomaDir,
 	}
 }
@@ -104,7 +100,7 @@
 		rest := ss[i+len(mvCmd):]
 		ei := strings.IndexByte(rest, ')')
 		if ei < 0 {
-			panic(ss)
+			return "", fmt.Errorf("unbalanced parenthes? %s", ss)
 		}
 		return rest[:ei], nil
 	}
@@ -175,7 +171,7 @@
 		if cmd == "" {
 			cmd = "true"
 		}
-		if n.gomaDir != "" && n.ccRe.MatchString(cmd) {
+		if n.gomaDir != "" && ccRE.MatchString(cmd) {
 			cmd = fmt.Sprintf("%s/gomacc %s", n.gomaDir, cmd)
 			useGomacc = true
 		}
@@ -229,17 +225,20 @@
 	return dep
 }
 
-func (n *ninjaGenerator) emitNode(node *DepNode) {
+func (n *ninjaGenerator) emitNode(node *DepNode) error {
 	if n.done[node.Output] {
-		return
+		return nil
 	}
 	n.done[node.Output] = true
 
 	if len(node.Cmds) == 0 && len(node.Deps) == 0 && !node.IsPhony {
-		return
+		return nil
 	}
 
-	runners, _ := n.ex.createRunners(node, true)
+	runners, _, err := n.ex.createRunners(node, true)
+	if err != nil {
+		return err
+	}
 	ruleName := "phony"
 	useLocalPool := false
 	if len(runners) > 0 {
@@ -253,7 +252,7 @@
 		}
 		depfile, err := getDepfile(ss)
 		if err != nil {
-			panic(err)
+			return err
 		}
 		if depfile != "" {
 			fmt.Fprintf(n.f, " depfile = %s\n", depfile)
@@ -275,26 +274,39 @@
 	}
 
 	for _, d := range node.Deps {
-		n.emitNode(d)
+		err := n.emitNode(d)
+		if err != nil {
+			return err
+		}
 	}
+	return nil
 }
 
-func (n *ninjaGenerator) generateShell() {
+func (n *ninjaGenerator) generateShell() (err error) {
 	f, err := os.Create("ninja.sh")
 	if err != nil {
-		panic(err)
+		return err
 	}
-	defer f.Close()
+	defer func() {
+		cerr := f.Close()
+		if err == nil {
+			err = cerr
+		}
+	}()
 
 	ev := NewEvaluator(n.vars)
-	shell := ev.EvaluateVar("SHELL")
-	if shell == "" {
+	shell, err := ev.EvaluateVar("SHELL")
+	if err != nil {
 		shell = "/bin/sh"
 	}
 	fmt.Fprintf(f, "#!%s\n", shell)
 	for name, export := range n.exports {
 		if export {
-			fmt.Fprintf(f, "export %s=%s\n", name, ev.EvaluateVar(name))
+			v, err := ev.EvaluateVar(name)
+			if err != nil {
+				return err
+			}
+			fmt.Fprintf(f, "export %s=%s\n", name, v)
 		} else {
 			fmt.Fprintf(f, "unset %s\n", name)
 		}
@@ -305,18 +317,20 @@
 		fmt.Fprintln(f, `exec ninja -j300 "$@"`)
 	}
 
-	err = f.Chmod(0755)
-	if err != nil {
-		panic(err)
-	}
+	return f.Chmod(0755)
 }
 
-func (n *ninjaGenerator) generateNinja() {
+func (n *ninjaGenerator) generateNinja() (err error) {
 	f, err := os.Create("build.ninja")
 	if err != nil {
-		panic(err)
+		return err
 	}
-	defer f.Close()
+	defer func() {
+		cerr := f.Close()
+		if err == nil {
+			err = cerr
+		}
+	}()
 
 	n.f = f
 	fmt.Fprintf(n.f, "# Generated by kati\n")
@@ -327,16 +341,31 @@
 		fmt.Fprintf(n.f, " depth = %d\n", runtime.NumCPU())
 	}
 
-	n.ex = NewExecutor(n.vars, nil)
-	for _, node := range n.nodes {
-		n.emitNode(node)
+	n.ex, err = NewExecutor(n.vars, nil)
+	if err != nil {
+		return err
 	}
+	for _, node := range n.nodes {
+		err := n.emitNode(node)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
 }
 
-func GenerateNinja(g *DepGraph, gomaDir string) {
+// GenerateNinja generates build.ninja from DepGraph.
+func GenerateNinja(g *DepGraph, gomaDir string) error {
 	startTime := time.Now()
 	n := newNinjaGenerator(g, gomaDir)
-	n.generateShell()
-	n.generateNinja()
+	err := n.generateShell()
+	if err != nil {
+		return err
+	}
+	err = n.generateNinja()
+	if err != nil {
+		return err
+	}
 	logStats("generate ninja time: %q", time.Since(startTime))
+	return nil
 }