Home | History | Annotate | Download | only in gc
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // +build ignore
      6 
      7 // Generate builtin.go from $* (runtime.go and unsafe.go).
      8 // Run this after changing runtime.go and unsafe.go
      9 // or after changing the export metadata format in the compiler.
     10 // Either way, you need to have a working compiler binary first.
     11 package main
     12 
     13 import (
     14 	"bufio"
     15 	"fmt"
     16 	"io"
     17 	"log"
     18 	"os"
     19 	"os/exec"
     20 	"strings"
     21 )
     22 
     23 func main() {
     24 	f, err := os.Create("builtin.go")
     25 	if err != nil {
     26 		log.Fatal(err)
     27 	}
     28 	defer f.Close()
     29 	w := bufio.NewWriter(f)
     30 
     31 	fmt.Fprintln(w, "// AUTO-GENERATED by mkbuiltin.go; DO NOT EDIT")
     32 	fmt.Fprintln(w, "")
     33 	fmt.Fprintln(w, "package gc")
     34 
     35 	for _, name := range os.Args[1:] {
     36 		mkbuiltin(w, name)
     37 	}
     38 
     39 	if err := w.Flush(); err != nil {
     40 		log.Fatal(err)
     41 	}
     42 }
     43 
     44 // Compile .go file, import data from .6 file, and write Go string version.
     45 func mkbuiltin(w io.Writer, name string) {
     46 	if err := exec.Command("go", "tool", "compile", "-A", "builtin/"+name+".go").Run(); err != nil {
     47 		log.Fatal(err)
     48 	}
     49 	obj := name + ".o"
     50 	defer os.Remove(obj)
     51 
     52 	r, err := os.Open(obj)
     53 	if err != nil {
     54 		log.Fatal(err)
     55 	}
     56 	defer r.Close()
     57 	scanner := bufio.NewScanner(r)
     58 
     59 	// Look for $$ that introduces imports.
     60 	for scanner.Scan() {
     61 		if strings.Contains(scanner.Text(), "$$") {
     62 			goto Begin
     63 		}
     64 	}
     65 	log.Fatal("did not find beginning of imports")
     66 
     67 Begin:
     68 	initfunc := fmt.Sprintf("init_%s_function", name)
     69 
     70 	fmt.Fprintf(w, "\nconst %simport = \"\" +\n", name)
     71 
     72 	// sys.go claims to be in package PACKAGE to avoid
     73 	// conflicts during "go tool compile sys.go".  Rename PACKAGE to $2.
     74 	replacer := strings.NewReplacer("PACKAGE", name)
     75 
     76 	// Process imports, stopping at $$ that closes them.
     77 	for scanner.Scan() {
     78 		p := scanner.Text()
     79 		if strings.Contains(p, "$$") {
     80 			goto End
     81 		}
     82 
     83 		// Chop leading white space.
     84 		p = strings.TrimLeft(p, " \t")
     85 
     86 		// Cut out decl of init_$1_function - it doesn't exist.
     87 		if strings.Contains(p, initfunc) {
     88 			continue
     89 		}
     90 
     91 		fmt.Fprintf(w, "\t%q +\n", replacer.Replace(p)+"\n")
     92 	}
     93 	log.Fatal("did not find end of imports")
     94 
     95 End:
     96 	fmt.Fprintf(w, "\t\"$$\\n\"\n")
     97 }
     98