// +build ignore
-// Generate builtin.go from builtin/runtime.go and builtin/unsafe.go
-// (passed as arguments on the command line by a go:generate comment).
+// Generate builtin.go from builtin/runtime.go and builtin/unsafe.go.
// Run this after changing builtin/runtime.go and builtin/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"
+ "bytes"
"fmt"
"io"
+ "io/ioutil"
"log"
"os"
"os/exec"
- "strings"
)
func main() {
- 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")
+ var b bytes.Buffer
+ fmt.Fprintln(&b, "// AUTO-GENERATED by mkbuiltin.go; DO NOT EDIT")
+ fmt.Fprintln(&b, "")
+ fmt.Fprintln(&b, "package gc")
- for _, name := range os.Args[1:] {
- mkbuiltin(w, name)
- }
+ mkbuiltin(&b, "runtime")
+ mkbuiltin(&b, "unsafe")
- if err := w.Flush(); err != nil {
+ if err := ioutil.WriteFile("builtin.go", b.Bytes(), 0666); err != nil {
log.Fatal(err)
}
}
-// Compile .go file, import data from .6 file, and write Go string version.
+// Compile .go file, import data from .o file, and write Go string version.
func mkbuiltin(w io.Writer, name string) {
- if err := exec.Command("go", "tool", "compile", "-A", "builtin/"+name+".go").Run(); err != nil {
+ args := []string{"tool", "compile", "-A"}
+ if name == "runtime" {
+ args = append(args, "-u")
+ }
+ args = append(args, "builtin/"+name+".go")
+
+ if err := exec.Command("go", args...).Run(); err != nil {
log.Fatal(err)
}
obj := name + ".o"
defer os.Remove(obj)
- r, err := os.Open(obj)
+ b, err := ioutil.ReadFile(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
- }
+ i := bytes.Index(b, []byte("\n$$\n"))
+ if i < 0 {
+ log.Fatal("did not find beginning of imports")
}
- log.Fatal("did not find beginning of imports")
+ i += 4
-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 "go tool compile 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
- }
+ // Look for $$ that closes imports.
+ j := bytes.Index(b[i:], []byte("\n$$\n"))
+ if j < 0 {
+ log.Fatal("did not find end of imports")
+ }
+ j += i + 4
+ // Process and reformat imports.
+ fmt.Fprintf(w, "\nconst %simport = \"\"", name)
+ for _, p := range bytes.SplitAfter(b[i:j], []byte("\n")) {
// 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) {
+ p = bytes.TrimLeft(p, " \t")
+ if len(p) == 0 {
continue
}
- fmt.Fprintf(w, "\t%q +\n", replacer.Replace(p)+"\n")
+ fmt.Fprintf(w, " +\n\t%q", p)
}
- log.Fatal("did not find end of imports")
-
-End:
- fmt.Fprintf(w, "\t\"$$\\n\"\n")
+ fmt.Fprintf(w, "\n")
}