mkstdlib.go

  1// +build ignore
  2
  3// mkstdlib generates the zstdlib.go file, containing the Go standard
  4// library API symbols. It's baked into the binary to avoid scanning
  5// GOPATH in the common case.
  6package main
  7
  8import (
  9	"bufio"
 10	"bytes"
 11	"fmt"
 12	"go/format"
 13	"io"
 14	"io/ioutil"
 15	"log"
 16	"os"
 17	"path"
 18	"path/filepath"
 19	"regexp"
 20	"runtime"
 21	"sort"
 22	"strings"
 23)
 24
 25func mustOpen(name string) io.Reader {
 26	f, err := os.Open(name)
 27	if err != nil {
 28		log.Fatal(err)
 29	}
 30	return f
 31}
 32
 33func api(base string) string {
 34	return filepath.Join(runtime.GOROOT(), "api", base)
 35}
 36
 37var sym = regexp.MustCompile(`^pkg (\S+).*?, (?:var|func|type|const) ([A-Z]\w*)`)
 38
 39func main() {
 40	var buf bytes.Buffer
 41	outf := func(format string, args ...interface{}) {
 42		fmt.Fprintf(&buf, format, args...)
 43	}
 44	outf("// Code generated by mkstdlib.go. DO NOT EDIT.\n\n")
 45	outf("package imports\n")
 46	outf("var stdlib = map[string]string{\n")
 47	f := io.MultiReader(
 48		mustOpen(api("go1.txt")),
 49		mustOpen(api("go1.1.txt")),
 50		mustOpen(api("go1.2.txt")),
 51		mustOpen(api("go1.3.txt")),
 52		mustOpen(api("go1.4.txt")),
 53		mustOpen(api("go1.5.txt")),
 54		mustOpen(api("go1.6.txt")),
 55		mustOpen(api("go1.7.txt")),
 56		mustOpen(api("go1.8.txt")),
 57		mustOpen(api("go1.9.txt")),
 58		mustOpen(api("go1.10.txt")),
 59	)
 60	sc := bufio.NewScanner(f)
 61	fullImport := map[string]string{} // "zip.NewReader" => "archive/zip"
 62	ambiguous := map[string]bool{}
 63	var keys []string
 64	for sc.Scan() {
 65		l := sc.Text()
 66		has := func(v string) bool { return strings.Contains(l, v) }
 67		if has("struct, ") || has("interface, ") || has(", method (") {
 68			continue
 69		}
 70		if m := sym.FindStringSubmatch(l); m != nil {
 71			full := m[1]
 72			key := path.Base(full) + "." + m[2]
 73			if exist, ok := fullImport[key]; ok {
 74				if exist != full {
 75					ambiguous[key] = true
 76				}
 77			} else {
 78				fullImport[key] = full
 79				keys = append(keys, key)
 80			}
 81		}
 82	}
 83	if err := sc.Err(); err != nil {
 84		log.Fatal(err)
 85	}
 86	sort.Strings(keys)
 87	for _, key := range keys {
 88		if ambiguous[key] {
 89			outf("\t// %q is ambiguous\n", key)
 90		} else {
 91			outf("\t%q: %q,\n", key, fullImport[key])
 92		}
 93	}
 94	outf("\n")
 95	for _, sym := range [...]string{"Alignof", "ArbitraryType", "Offsetof", "Pointer", "Sizeof"} {
 96		outf("\t%q: %q,\n", "unsafe."+sym, "unsafe")
 97	}
 98	outf("}\n")
 99	fmtbuf, err := format.Source(buf.Bytes())
100	if err != nil {
101		log.Fatal(err)
102	}
103	err = ioutil.WriteFile("zstdlib.go", fmtbuf, 0666)
104	if err != nil {
105		log.Fatal(err)
106	}
107}