github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/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  package main
    12  
    13  import (
    14  	"bytes"
    15  	"flag"
    16  	"fmt"
    17  	"io"
    18  	"io/ioutil"
    19  	"log"
    20  	"os"
    21  	"os/exec"
    22  )
    23  
    24  var stdout = flag.Bool("stdout", false, "write to stdout instead of builtin.go")
    25  
    26  func main() {
    27  	flag.Parse()
    28  
    29  	var b bytes.Buffer
    30  	fmt.Fprintln(&b, "// AUTO-GENERATED by mkbuiltin.go; DO NOT EDIT")
    31  	fmt.Fprintln(&b, "")
    32  	fmt.Fprintln(&b, "package gc")
    33  
    34  	mkbuiltin(&b, "runtime")
    35  	mkbuiltin(&b, "unsafe")
    36  
    37  	var err error
    38  	if *stdout {
    39  		_, err = os.Stdout.Write(b.Bytes())
    40  	} else {
    41  		err = ioutil.WriteFile("builtin.go", b.Bytes(), 0666)
    42  	}
    43  	if err != nil {
    44  		log.Fatal(err)
    45  	}
    46  }
    47  
    48  // Compile .go file, import data from .o file, and write Go string version.
    49  func mkbuiltin(w io.Writer, name string) {
    50  	args := []string{"tool", "compile", "-A"}
    51  	if name == "runtime" {
    52  		args = append(args, "-u")
    53  	}
    54  	args = append(args, "builtin/"+name+".go")
    55  
    56  	if err := exec.Command("go", args...).Run(); err != nil {
    57  		log.Fatal(err)
    58  	}
    59  	obj := name + ".o"
    60  	defer os.Remove(obj)
    61  
    62  	b, err := ioutil.ReadFile(obj)
    63  	if err != nil {
    64  		log.Fatal(err)
    65  	}
    66  
    67  	// Look for $$B that introduces binary export data.
    68  	textual := false // TODO(gri) remove once we switched to binary export format
    69  	i := bytes.Index(b, []byte("\n$$B\n"))
    70  	if i < 0 {
    71  		// Look for $$ that introduces textual export data.
    72  		i = bytes.Index(b, []byte("\n$$\n"))
    73  		if i < 0 {
    74  			log.Fatal("did not find beginning of export data")
    75  		}
    76  		textual = true
    77  		i-- // textual data doesn't have B
    78  	}
    79  	b = b[i+5:]
    80  
    81  	// Look for $$ that closes export data.
    82  	i = bytes.Index(b, []byte("\n$$\n"))
    83  	if i < 0 {
    84  		log.Fatal("did not find end of export data")
    85  	}
    86  	b = b[:i+4]
    87  
    88  	// Process and reformat export data.
    89  	fmt.Fprintf(w, "\nconst %simport = \"\"", name)
    90  	if textual {
    91  		for _, p := range bytes.SplitAfter(b, []byte("\n")) {
    92  			// Chop leading white space.
    93  			p = bytes.TrimLeft(p, " \t")
    94  			if len(p) == 0 {
    95  				continue
    96  			}
    97  
    98  			fmt.Fprintf(w, " +\n\t%q", p)
    99  		}
   100  	} else {
   101  		const n = 40 // number of bytes per line
   102  		for len(b) > 0 {
   103  			i := len(b)
   104  			if i > n {
   105  				i = n
   106  			}
   107  			fmt.Fprintf(w, " +\n\t%q", b[:i])
   108  			b = b[i:]
   109  		}
   110  	}
   111  	fmt.Fprintf(w, "\n")
   112  }