github.com/euank/go@v0.0.0-20160829210321-495514729181/src/cmd/compile/internal/gc/mkbuiltin.go (about)

     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 builtin/runtime.go and builtin/unsafe.go.
     8  // Run this after changing builtin/runtime.go and builtin/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  // See bexport.go for how to make an export metadata format change.
    12  package main
    13  
    14  import (
    15  	"bytes"
    16  	"flag"
    17  	"fmt"
    18  	"io"
    19  	"io/ioutil"
    20  	"log"
    21  	"os"
    22  	"os/exec"
    23  )
    24  
    25  var stdout = flag.Bool("stdout", false, "write to stdout instead of builtin.go")
    26  
    27  func main() {
    28  	flag.Parse()
    29  
    30  	var b bytes.Buffer
    31  	fmt.Fprintln(&b, "// AUTO-GENERATED by mkbuiltin.go; DO NOT EDIT")
    32  	fmt.Fprintln(&b, "")
    33  	fmt.Fprintln(&b, "package gc")
    34  
    35  	mkbuiltin(&b, "runtime")
    36  	mkbuiltin(&b, "unsafe")
    37  
    38  	var err error
    39  	if *stdout {
    40  		_, err = os.Stdout.Write(b.Bytes())
    41  	} else {
    42  		err = ioutil.WriteFile("builtin.go", b.Bytes(), 0666)
    43  	}
    44  	if err != nil {
    45  		log.Fatal(err)
    46  	}
    47  }
    48  
    49  // Compile .go file, import data from .o file, and write Go string version.
    50  func mkbuiltin(w io.Writer, name string) {
    51  	args := []string{"tool", "compile", "-A"}
    52  	if name == "runtime" {
    53  		args = append(args, "-u")
    54  	}
    55  	args = append(args, "builtin/"+name+".go")
    56  
    57  	if err := exec.Command("go", args...).Run(); err != nil {
    58  		log.Fatal(err)
    59  	}
    60  	obj := name + ".o"
    61  	defer os.Remove(obj)
    62  
    63  	b, err := ioutil.ReadFile(obj)
    64  	if err != nil {
    65  		log.Fatal(err)
    66  	}
    67  
    68  	// Look for $$B that introduces binary export data.
    69  	i := bytes.Index(b, []byte("\n$$B\n"))
    70  	if i < 0 {
    71  		log.Fatal("did not find beginning of export data")
    72  	}
    73  	b = b[i+5:]
    74  
    75  	// Look for $$ that closes export data.
    76  	i = bytes.Index(b, []byte("\n$$\n"))
    77  	if i < 0 {
    78  		log.Fatal("did not find end of export data")
    79  	}
    80  	b = b[:i+4]
    81  
    82  	// Process and reformat export data.
    83  	const n = 40 // number of bytes per line
    84  	fmt.Fprintf(w, "\nconst %simport = \"\"", name)
    85  	for len(b) > 0 {
    86  		i := len(b)
    87  		if i > n {
    88  			i = n
    89  		}
    90  		fmt.Fprintf(w, " +\n\t%q", b[:i])
    91  		b = b[i:]
    92  	}
    93  	fmt.Fprintf(w, "\n")
    94  }