github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/net/ipv6/gen.go (about)

     1  // Copyright 2013 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  //go:generate go run gen.go
     8  
     9  // This program generates system adaptation constants and types,
    10  // internet protocol constants and tables by reading template files
    11  // and IANA protocol registries.
    12  package main
    13  
    14  import (
    15  	"bytes"
    16  	"encoding/xml"
    17  	"fmt"
    18  	"go/format"
    19  	"io"
    20  	"io/ioutil"
    21  	"net/http"
    22  	"os"
    23  	"os/exec"
    24  	"runtime"
    25  	"strconv"
    26  	"strings"
    27  )
    28  
    29  func main() {
    30  	if err := genzsys(); err != nil {
    31  		fmt.Fprintln(os.Stderr, err)
    32  		os.Exit(1)
    33  	}
    34  	if err := geniana(); err != nil {
    35  		fmt.Fprintln(os.Stderr, err)
    36  		os.Exit(1)
    37  	}
    38  }
    39  
    40  func genzsys() error {
    41  	defs := "defs_" + runtime.GOOS + ".go"
    42  	f, err := os.Open(defs)
    43  	if err != nil {
    44  		if os.IsNotExist(err) {
    45  			return nil
    46  		}
    47  		return err
    48  	}
    49  	f.Close()
    50  	cmd := exec.Command("go", "tool", "cgo", "-godefs", defs)
    51  	b, err := cmd.Output()
    52  	if err != nil {
    53  		return err
    54  	}
    55  	// The ipv6 pacakge still supports go1.2, and so we need to
    56  	// take care of additional platforms in go1.3 and above for
    57  	// working with go1.2.
    58  	switch {
    59  	case runtime.GOOS == "dragonfly" || runtime.GOOS == "solaris":
    60  		b = bytes.Replace(b, []byte("package ipv6\n"), []byte("// +build "+runtime.GOOS+"\n\npackage ipv6\n"), 1)
    61  	case runtime.GOOS == "linux" && (runtime.GOARCH == "arm64" || runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le"):
    62  		b = bytes.Replace(b, []byte("package ipv6\n"), []byte("// +build "+runtime.GOOS+","+runtime.GOARCH+"\n\npackage ipv6\n"), 1)
    63  	}
    64  	b, err = format.Source(b)
    65  	if err != nil {
    66  		return err
    67  	}
    68  	zsys := "zsys_" + runtime.GOOS + ".go"
    69  	switch runtime.GOOS {
    70  	case "freebsd", "linux":
    71  		zsys = "zsys_" + runtime.GOOS + "_" + runtime.GOARCH + ".go"
    72  	}
    73  	if err := ioutil.WriteFile(zsys, b, 0644); err != nil {
    74  		return err
    75  	}
    76  	return nil
    77  }
    78  
    79  var registries = []struct {
    80  	url   string
    81  	parse func(io.Writer, io.Reader) error
    82  }{
    83  	{
    84  		"http://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xml",
    85  		parseICMPv6Parameters,
    86  	},
    87  }
    88  
    89  func geniana() error {
    90  	var bb bytes.Buffer
    91  	fmt.Fprintf(&bb, "// go generate gen.go\n")
    92  	fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
    93  	fmt.Fprintf(&bb, "package ipv6\n\n")
    94  	for _, r := range registries {
    95  		resp, err := http.Get(r.url)
    96  		if err != nil {
    97  			return err
    98  		}
    99  		defer resp.Body.Close()
   100  		if resp.StatusCode != http.StatusOK {
   101  			return fmt.Errorf("got HTTP status code %v for %v\n", resp.StatusCode, r.url)
   102  		}
   103  		if err := r.parse(&bb, resp.Body); err != nil {
   104  			return err
   105  		}
   106  		fmt.Fprintf(&bb, "\n")
   107  	}
   108  	b, err := format.Source(bb.Bytes())
   109  	if err != nil {
   110  		return err
   111  	}
   112  	if err := ioutil.WriteFile("iana.go", b, 0644); err != nil {
   113  		return err
   114  	}
   115  	return nil
   116  }
   117  
   118  func parseICMPv6Parameters(w io.Writer, r io.Reader) error {
   119  	dec := xml.NewDecoder(r)
   120  	var icp icmpv6Parameters
   121  	if err := dec.Decode(&icp); err != nil {
   122  		return err
   123  	}
   124  	prs := icp.escape()
   125  	fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
   126  	fmt.Fprintf(w, "const (\n")
   127  	for _, pr := range prs {
   128  		if pr.Name == "" {
   129  			continue
   130  		}
   131  		fmt.Fprintf(w, "ICMPType%s ICMPType = %d", pr.Name, pr.Value)
   132  		fmt.Fprintf(w, "// %s\n", pr.OrigName)
   133  	}
   134  	fmt.Fprintf(w, ")\n\n")
   135  	fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
   136  	fmt.Fprintf(w, "var icmpTypes = map[ICMPType]string{\n")
   137  	for _, pr := range prs {
   138  		if pr.Name == "" {
   139  			continue
   140  		}
   141  		fmt.Fprintf(w, "%d: %q,\n", pr.Value, strings.ToLower(pr.OrigName))
   142  	}
   143  	fmt.Fprintf(w, "}\n")
   144  	return nil
   145  }
   146  
   147  type icmpv6Parameters struct {
   148  	XMLName    xml.Name `xml:"registry"`
   149  	Title      string   `xml:"title"`
   150  	Updated    string   `xml:"updated"`
   151  	Registries []struct {
   152  		Title   string `xml:"title"`
   153  		Records []struct {
   154  			Value string `xml:"value"`
   155  			Name  string `xml:"name"`
   156  		} `xml:"record"`
   157  	} `xml:"registry"`
   158  }
   159  
   160  type canonICMPv6ParamRecord struct {
   161  	OrigName string
   162  	Name     string
   163  	Value    int
   164  }
   165  
   166  func (icp *icmpv6Parameters) escape() []canonICMPv6ParamRecord {
   167  	id := -1
   168  	for i, r := range icp.Registries {
   169  		if strings.Contains(r.Title, "Type") || strings.Contains(r.Title, "type") {
   170  			id = i
   171  			break
   172  		}
   173  	}
   174  	if id < 0 {
   175  		return nil
   176  	}
   177  	prs := make([]canonICMPv6ParamRecord, len(icp.Registries[id].Records))
   178  	sr := strings.NewReplacer(
   179  		"Messages", "",
   180  		"Message", "",
   181  		"ICMP", "",
   182  		"+", "P",
   183  		"-", "",
   184  		"/", "",
   185  		".", "",
   186  		" ", "",
   187  	)
   188  	for i, pr := range icp.Registries[id].Records {
   189  		if strings.Contains(pr.Name, "Reserved") ||
   190  			strings.Contains(pr.Name, "Unassigned") ||
   191  			strings.Contains(pr.Name, "Deprecated") ||
   192  			strings.Contains(pr.Name, "Experiment") ||
   193  			strings.Contains(pr.Name, "experiment") {
   194  			continue
   195  		}
   196  		ss := strings.Split(pr.Name, "\n")
   197  		if len(ss) > 1 {
   198  			prs[i].Name = strings.Join(ss, " ")
   199  		} else {
   200  			prs[i].Name = ss[0]
   201  		}
   202  		s := strings.TrimSpace(prs[i].Name)
   203  		prs[i].OrigName = s
   204  		prs[i].Name = sr.Replace(s)
   205  		prs[i].Value, _ = strconv.Atoi(pr.Value)
   206  	}
   207  	return prs
   208  }