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