cmd/internal/gc: restore mkbuiltin

Change-Id: I6cc4061fef9d3c3530406ab3d4811192b7175e89
Reviewed-on: https://go-review.googlesource.com/6233
Reviewed-by: Minux Ma <minux@golang.org>
diff --git a/src/cmd/internal/gc/mkbuiltin.go b/src/cmd/internal/gc/mkbuiltin.go
new file mode 100644
index 0000000..f32a75b
--- /dev/null
+++ b/src/cmd/internal/gc/mkbuiltin.go
@@ -0,0 +1,104 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// Generate builtin.go from $* (runtime.go and unsafe.go).
+// Run this after changing runtime.go and unsafe.go
+// or after changing the export metadata format in the compiler.
+// Either way, you need to have a working compiler binary first.
+package main
+
+import (
+	"bufio"
+	"fmt"
+	"go/build"
+	"io"
+	"log"
+	"os"
+	"os/exec"
+	"runtime"
+	"strings"
+)
+
+func main() {
+	gochar, err := build.ArchChar(runtime.GOARCH)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	f, err := os.Create("builtin.go")
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer f.Close()
+	w := bufio.NewWriter(f)
+
+	fmt.Fprintln(w, "// AUTO-GENERATED by mkbuiltin.go; DO NOT EDIT")
+	fmt.Fprintln(w, "")
+	fmt.Fprintln(w, "package gc")
+
+	for _, name := range os.Args[1:] {
+		mkbuiltin(w, gochar, name)
+	}
+
+	if err := w.Flush(); err != nil {
+		log.Fatal(err)
+	}
+}
+
+// Compile .go file, import data from .6 file, and write Go string version.
+func mkbuiltin(w io.Writer, gochar string, name string) {
+	if err := exec.Command("go", "tool", gochar+"g", "-A", "builtins/"+name+".go").Run(); err != nil {
+		log.Fatal(err)
+	}
+	obj := fmt.Sprintf("%s.%s", name, gochar)
+	defer os.Remove(obj)
+
+	r, err := os.Open(obj)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer r.Close()
+	scanner := bufio.NewScanner(r)
+
+	// Look for $$ that introduces imports.
+	for scanner.Scan() {
+		if strings.Contains(scanner.Text(), "$$") {
+			goto Begin
+		}
+	}
+	log.Fatal("did not find beginning of imports")
+
+Begin:
+	initfunc := fmt.Sprintf("init_%s_function", name)
+
+	fmt.Fprintf(w, "\nconst %simport = \"\" +\n", name)
+
+	// sys.go claims to be in package PACKAGE to avoid
+	// conflicts during "6g sys.go".  Rename PACKAGE to $2.
+	replacer := strings.NewReplacer("PACKAGE", name)
+
+	// Process imports, stopping at $$ that closes them.
+	for scanner.Scan() {
+		p := scanner.Text()
+		if strings.Contains(p, "$$") {
+			goto End
+		}
+
+		// Chop leading white space.
+		p = strings.TrimLeft(p, " \t")
+
+		// Cut out decl of init_$1_function - it doesn't exist.
+		if strings.Contains(p, initfunc) {
+			continue
+		}
+
+		fmt.Fprintf(w, "\t%q +\n", replacer.Replace(p)+"\n")
+	}
+	log.Fatal("did not find end of imports")
+
+End:
+	fmt.Fprintf(w, "\t\"$$\\n\"\n")
+}