github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/cmd/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 $* (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  	"go/build"
    17  	"io"
    18  	"log"
    19  	"os"
    20  	"os/exec"
    21  	"runtime"
    22  	"strings"
    23  )
    24  
    25  func main() {
    26  	gochar, err := build.ArchChar(runtime.GOARCH)
    27  	if err != nil {
    28  		log.Fatal(err)
    29  	}
    30  
    31  	f, err := os.Create("builtin.go")
    32  	if err != nil {
    33  		log.Fatal(err)
    34  	}
    35  	defer f.Close()
    36  	w := bufio.NewWriter(f)
    37  
    38  	fmt.Fprintln(w, "// AUTO-GENERATED by mkbuiltin.go; DO NOT EDIT")
    39  	fmt.Fprintln(w, "")
    40  	fmt.Fprintln(w, "package gc")
    41  
    42  	for _, name := range os.Args[1:] {
    43  		mkbuiltin(w, gochar, name)
    44  	}
    45  
    46  	if err := w.Flush(); err != nil {
    47  		log.Fatal(err)
    48  	}
    49  }
    50  
    51  // Compile .go file, import data from .6 file, and write Go string version.
    52  func mkbuiltin(w io.Writer, gochar string, name string) {
    53  	if err := exec.Command("go", "tool", gochar+"g", "-A", "builtin/"+name+".go").Run(); err != nil {
    54  		log.Fatal(err)
    55  	}
    56  	obj := fmt.Sprintf("%s.%s", name, gochar)
    57  	defer os.Remove(obj)
    58  
    59  	r, err := os.Open(obj)
    60  	if err != nil {
    61  		log.Fatal(err)
    62  	}
    63  	defer r.Close()
    64  	scanner := bufio.NewScanner(r)
    65  
    66  	// Look for $$ that introduces imports.
    67  	for scanner.Scan() {
    68  		if strings.Contains(scanner.Text(), "$$") {
    69  			goto Begin
    70  		}
    71  	}
    72  	log.Fatal("did not find beginning of imports")
    73  
    74  Begin:
    75  	initfunc := fmt.Sprintf("init_%s_function", name)
    76  
    77  	fmt.Fprintf(w, "\nconst %simport = \"\" +\n", name)
    78  
    79  	// sys.go claims to be in package PACKAGE to avoid
    80  	// conflicts during "6g sys.go".  Rename PACKAGE to $2.
    81  	replacer := strings.NewReplacer("PACKAGE", name)
    82  
    83  	// Process imports, stopping at $$ that closes them.
    84  	for scanner.Scan() {
    85  		p := scanner.Text()
    86  		if strings.Contains(p, "$$") {
    87  			goto End
    88  		}
    89  
    90  		// Chop leading white space.
    91  		p = strings.TrimLeft(p, " \t")
    92  
    93  		// Cut out decl of init_$1_function - it doesn't exist.
    94  		if strings.Contains(p, initfunc) {
    95  			continue
    96  		}
    97  
    98  		fmt.Fprintf(w, "\t%q +\n", replacer.Replace(p)+"\n")
    99  	}
   100  	log.Fatal("did not find end of imports")
   101  
   102  End:
   103  	fmt.Fprintf(w, "\t\"$$\\n\"\n")
   104  }